Gidon - 基于 Avalonia 的 MVVM 插件 IoC 容器

Avalonia 的 Gidon IoC/MVVM 框架
在本文中,我介绍了一个新的Gidon IoC/MVVM 框架,该框架是在我自己的IoCy控制反转/依赖注入容器之上为一个很棒的多平台类 WPF 包Avalonia构建的。据我所知,它是 Avalonia 的第一个 IoC/MVVM 框架,尽管我知道之前有一些尝试(不确定成功与否)为 Avalonia 移植 Prism/MEF。

所以合理的问题是为什么不直接移植 Prism(或使用它以前的移植)而不是构建一个新框架?

在我看来,它经常使用的 Prism 和 MEF 过于复杂,允许使用一些不应与 WPF 和 Avalonia 一起使用的旧范例(例如,事件聚合)并且文档非常少。

Gidon 的目的是提供非常简单的 API 和实现,但涵盖所有需要的功能。

请注意,Gidon 框架已经非常可操作(正如本文的示例将要展示的那样)。在不久的将来,它还会添加许多新的和很棒的功能。

复习模型-视图-视图模型 (MVVM) 模式
什么是 MVVM
MVVM 模式由三部分组成:

模型——来自后端的非可视化数据
视图模型——也是包含数据的非可视对象,但也提供非可视属性以反映可视按钮、菜单项等调用的可视功能和方法。
视图- 代表应用程序视觉效果的视觉对象
View Model 知道模型,但反之则不然。

View 是围绕 View Model 构建的,因此它有一些关于它的知识,但 View Model 不应该知道任何关于 View 的信息。

MVVM:视图知道视图模型,而视图模型又知道模型,反之亦然
View 通常是被动的——它只是模仿它的 View Model 并调用 View Model 的方法。View 只知道它自己的 View Model——不同 View 之间的所有通信通常都是通过它们各自的 View Model 完成的。

MVVM:视图之间的通信仅通过它们的视图模型完成
重要说明:视图与其视图模型之间的双向通信并不意味着视图模型对视图一无所知:从视图模型到视图的通信是通过绑定或事件实现的。

MVVM 模式的主要优点是视图的非常复杂的视觉对象只是模仿视图模型的更简单的非视觉对象。非可视视图模型对象更容易创建、扩展、测试和调试,并且由于所有业务逻辑都位于视图模型中,因此 MVVM 应用程序变得更容易构建和维护。

MVVM 模式最初是为 WPF 开发而发明的,因为 WPF 具有超强的绑定能力,但后来也被其他工具和框架所采用。当然,每个 XAML 框架(包括 Avalonia、UWP、Xamarin 等)都支持 MVVM,但 Angular 和 Knockout JavaScript 包本质上也是 MVVM 框架。

在您的代码中遵循 MVVM 模式,通常不需要任何控制反转或依赖注入。

重要说明:在我广泛的实践中,很少需要模型——后端数据可以直接反序列化到视图模型类中。因此,我主要在没有模型的情况下练习视图-视图模型 (VVM) 模式,但为了简单起见,我将这两种方法都称为 MVVM。

要了解有关 MVVM 模式的更多信息,您可以阅读我的文章MVVM Pattern Made Simple或Data Templates and View Models。

用于 MVVM 的 Avalonia 工具
在 Avalonia 中将非可视视图模型转换为可视视图的最佳方法是使用ContentPresenter和ItemsPresenter控件(在 WPF 中,这将是ContentControl并且ItemsControl相应地)。

ContentPresenter通过将传递给其属性的视图模型对象“嫁接”到传递给其Content属性的视图模型对象,非常适合将单个非可视对象转换为可视对象:DataTemplateContenTemplate

图 3

ItemsPresenter通过将存储在其属性中的每个对象应用到它们中,非常适合将非可视视图模型对象(存储在其Items属性中)的集合转换为视觉对象集合。结果集合中的视觉效果根据属性提供的 Avalonia 排列(默认情况下,它们垂直堆叠,一个在下一个之上)。DataTemplateItemTemplatePanelItemsPresenter.ItemsPanel

图 4

复习控制反转 (IoC) 容器(无 MVVM)
MVVM 和 IoC 不必放在一起。有许多普通的控制反转(插件)容器,它们与 MVVM 或任何可视化框架无关。其中包括:

海洋基金会
Autofac
统一
忍射
温莎城堡
IoCy - 我自己的简单 IoC 容器可在IoCy 获得。
此类框架的主要目的是促进将功能拆分为松散耦合的插件(一些是静态加载的,一些是动态加载的),以改进应用程序中关注点的分离。

这将带来以下好处:

插件独立性——修改一个插件的实现不应触发其他插件的更改
更容易的可测试性和调试—​​—人们应该能够轻松地单独测试、调试和修改每个插件(连同它所依赖的插件),并且固定插件应该与应用程序的其余部分一起工作,而无需对其他插件进行任何更改。
改进了产品的可扩展性——当您需要新功能时,您知道为该特定扩展修改哪个插件,或者如果需要,您可以向现有插件添加新插件,仅在可能使用新 API 的地方进行修改.
我看到许多项目(不是由我设计和启动的)仅使用上面列出的最后一个优势 - 通过向其添加插件来扩展应用程序。另一方面,它们的插件是如此混合和相互依存,以至于不能在不影响其他插件的情况下删除其中一个插件。这是一个非常重要的错误 - 为了获得良好插件架构的好处,不同插件之间的相互依赖性应该是最小的,架构师的任务是确保这种情况。

从某种意义上说,插件类似于硬件卡,而插件接口很像插卡的插槽。


重要说明:更换、添加或删除插件应该像更换、添加或删除已打开的计算机中的计算机卡一样简单。如果不是这种情况,您的插件架构需要额外的工作。

测试插件应该像将卡放入硬件测试仪一样简单,发送一些输入并在测试仪中检查相应的输出。当然,首先应该为插件构建一个测试器。

但是,总的来说,软件插件与硬件卡相比具有以下优点:

在软件中生成一个插件对象的成本比在硬件中生成一张卡要小得多,因为使用多个相同类型的插件对象不会增加应用程序的成本。此外,同一类型的不同对象保证以相同的方式运行——软件缺陷是按类型而不是按对象计算的。
插件可以是分层的,即插件本身可以由不同的子插件组成(硬件插件也可以有一些子插件,但在软件中,层次结构可以根据需要包含任意多的级别)。
一些插件可以是单例的——在许多不同的地方使用相同的插件(这在硬件中当然是不可能的)。
请注意,虽然插件层次结构没问题,但插件永远不应交叉依赖或对等依赖。这意味着如果插件是逻辑对等的,它们不应该相互依赖 - 一个共同的功能应该分解到不同的插件或非插件 DLL 中。

为什么 IoC 和 MVVM 在一起?
上面已经说过,MVVM 可以在没有 IoC 的情况下进行实践,而 IoC 可以在没有 MVVM 的情况下进行实践,那么为什么我们需要一个框架来做这两者呢?原因是视图及其对应的视图模型是构建为插件的良好候选者。在这种情况下,每个开发人员都可以处理自己的 View/View Model 组合,与团队其他成员分开测试它们,然后将它们作为插件组合在一起,理想情况下一切都会正常工作。

当然,有时 View Model 并不是完全独立的——它们需要相互通信。通信机制可以通过称为服务的非可视化单例插件连接,有时甚至可以内置到框架中。

有几个众所周知的 IoC/MVVM 框架通常围绕 Microsoft 的 MEF 或 Unity IoC 容器构建,有些甚至可以与两者一起使用。所有这些最初都是为 WPF 创建的,但后来也适用于 Xamarin 和 UWP。其中包括:

棱镜
Caliburn/Caliburn.Micro
肚带
复习 IoCy 容器
在这里,我将描述我的IoCy简单而强大的容器的功能。我向其中添加了我喜欢的 MEF、Autofac 和 Ninject 的所有功能,同时跳过了未广泛使用的功能。

IoC 和 DI(依赖注入)实现的主要原则是可注入对象不是通过调用它们的构造函数来创建的,而是通过调用容器上的一些方法来创建或找到要返回的对象。容器是在返回对象的正确实现之前创建的。每个可注入对象都可能具有一些也是可注入的属性。在那种情况下,这些属性也从同一个容器中递归地填充等等。

你可能感兴趣的:(wpf)