这就是解决方案的部分效果。
由于我在Winforms环境中使用Onion Architecture,因此我拥有UI,Infrastructure和Core层。使用依赖注入将所有层松散耦合。我想要实现的是每当一个表格来自例如加载帐户表单(类库),其中所有依赖项应加载到UnityContainer中,即已注册的类型。这些依赖项是Core和Infrastructure项目中的接口和实现。
我的困惑是我应该在哪里编写代码来注册依赖项?这个应用程序的组合根是什么?请注意,例如,表格帐户表单,HR表单等都使用主Windows应用程序中的反射加载,该应用程序仅引用基本表单项目。
在Eben Roux的建议之后
以下是我在加载程序集时执行连线代码的方法:
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
所以现在我的问题是:
答案 0 :(得分:1)
使用这种类型的插件架构,您最终会有多个组合根(排序)。很可能只有你的插件知道并且可以连线的依赖关系。
因此,您的部分架构应该是加载插件。这可能发生在主要应用程序中的连接位(组合根)中,这将使每个插件有机会执行其连接。
由于并非所有插件都需要布线,因此可以通过使用单独的接口来明确说明:
public interface IDependencyWiring
{
public void WireUp(IDependencyContainer container); // <-- changed to conform to update
}
然后在主要作品根目录中:
foreach (var plugin in plugins)
{
var wiring = plugin as IDependencyWiring;
if (wiring != null)
{
wiring.WireUp(myContainer);
}
}
我希望这是有道理的。
<强>更新强>:
首先我会使用安全演员。 VB.NET世界中的TryCast
。您可以使用依赖项iversion通过使用您自己的接口从实际插件中删除Unity。像这样:
public interface IDependencyContainer
{
void Register(Type type);
void Register<T>();
void Resolve(Type type);
void Resolve<T>();
}
好吧,你会添加你需要的东西。然后,当我在顶部public void WireUp(IContainer container);
进行操作时,将参考文件传递给电子邮件中的容器。
Resolve
行为 有点问题,因为您似乎是朝着 服务定位器 的方向前进。尝试通过使用构造函数(或其他)注入来获得容器完成的尽可能多的解析。当然,这适用于 Singleton 组件。对于 Transient ,我宁愿使用 Singleton 工厂来接收IDependencyContainer
的实例(这样也会被注册),它会执行为你解决(创造,真的)。