在WinForms应用程序的Unity容器中加载依赖项
这就是解决方案的部分外观 因为我在Winforms环境中使用Onion架构,所以我有UI、基础结构和核心层。所有层都使用依赖项注入进行松散耦合。我想要实现的是,无论何时从Accounts Forms(类库)加载表单,该表单的所有依赖项都应该加载到UnityContainer中,即注册类型。这些依赖关系是核心和基础设施项目中存在的接口和实现 我的困惑是,我应该在哪里编写代码来注册依赖项?此应用程序的合成根是什么?请注意,来自帐户表单、人力资源表单等的表单都是使用主Windows应用程序中的反射加载的,该应用程序仅引用基本表单项目 在Eben Roux的建议之后 以下是加载程序集时执行wireup代码的方式:在WinForms应用程序的Unity容器中加载依赖项,winforms,dependency-injection,domain-driven-design,unity-container,onion-architecture,Winforms,Dependency Injection,Domain Driven Design,Unity Container,Onion Architecture,这就是解决方案的部分外观 因为我在Winforms环境中使用Onion架构,所以我有UI、基础结构和核心层。所有层都使用依赖项注入进行松散耦合。我想要实现的是,无论何时从Accounts Forms(类库)加载表单,该表单的所有依赖项都应该加载到UnityContainer中,即注册类型。这些依赖关系是核心和基础设施项目中存在的接口和实现 我的困惑是,我应该在哪里编写代码来注册依赖项?此应用程序的合成根是什么?请注意,来自帐户表单、人力资源表单等的表单都是使用主Windows应用程序中的反射加载
Dim assemb As System.Reflection.Assembly
...
...
If assemb IsNot Nothing Then
Dim type As Type = GetType(IDependencyWiring)
Dim modules As List(Of Type) = assemb.GetTypes().Where(Function(p) type.IsAssignableFrom(p) AndAlso p.IsClass).ToList()
For Each [module] As Type In modules
Dim argTypes As Type() = New Type() {}
Dim cInfo As ConstructorInfo = [module].GetConstructor(argTypes)
Dim dependencyWiringModule As IDependencyWiring = DirectCast(cInfo.Invoke(Nothing), IDependencyWiring)
dependencyWiringModule.WireUp()
Next
End If
以下是具有WireUp方法的模块:
Public Class AccountModule : Implements IDependencyWiring
Private Shared Container As IUnityContainer
Public Sub New()
Container = New UnityContainer()
End Sub
Public Sub WireUp() Implements IDependencyWiring.WireUp
Container.RegisterType(Of IInterface1, Class1)()
Container.RegisterType(Of IInterface2, Class2)()
Container.RegisterType(Of IInterface3, Class3)()
Container.RegisterType(Of IInterface4, Class4)()
End Sub
Public Shared Function Resolve(typeToResolve As Type) As Object
Return Container.Resolve(typeToResolve.GetType())()
End Function
End Class
因此,我现在的问题是:
使用这种类型的插件体系结构,您实际上会得到多个组合根(各种类型)。很可能会有一些依赖关系,只有您的插件知道并且可以连接起来 因此,架构的一部分应该是加载插件。这可能发生在主应用程序中的某个位置,即连接位(组合根),这将为每个插件提供执行其连接的机会 由于并非所有插件都需要布线,因此可以使用单独的接口来明确这一点:
public interface IDependencyWiring
{
public void WireUp(IDependencyContainer container); // <-- changed to conform to update
}
我希望这是有道理的
更新:
首先,我会使用安全石膏<在VB.NET世界中的code>TryCast。通过使用自己的接口,您可以使用dependency-iversion从实际插件中去除Unity。大概是这样的:
public interface IDependencyContainer
{
void Register(Type type);
void Register<T>();
void Resolve(Type type);
void Resolve<T>();
}
公共接口IDependencyContainer
{
无效登记簿(类型);
无效寄存器();
无效解析(类型);
无效解析();
}
好吧,你可以添加你需要的。然后在wire up中传入对容器的引用,就像我在toppublic void wire up(IContainer容器)中所做的那样代码>
Resolve
行为有些问题,因为您似乎正朝着服务定位器的方向前进。通过使用构造函数(或其他)注入,尝试让容器完成尽可能多的解析。当然,这适用于单例组件。对于暂时的我宁愿使用一个单例工厂,它接收IDependencyContainer
(这样它也会被注册),并为您进行解析(创建,真的)。插件是指帐户表单(类库)中加载的单个WinForm?那么我需要用这个接口继承表单吗?还可以在页面中实现wireup方法?插件通常在略高于表单的级别上工作。它代表一个组件(帐户、人力资源等),在插件中,您通常会拥有一些在主shell中可用的特定功能。因此,您不希望在表单上实现该接口。而是在类似于AccountModule
的东西上,让它来完成布线以及与在shell中提供模块功能相关的任何其他功能。感谢您的回答,Eben。我已经更新了我的问题,以显示我现在采取的方法。然而,我仍然有一些困惑。请看一看
public interface IDependencyContainer
{
void Register(Type type);
void Register<T>();
void Resolve(Type type);
void Resolve<T>();
}