1

解决方案结构(部分)

这就是解决方案部分的样子。

由于我在 Winforms 环境中使用洋葱架构,因此我有 UI、基础设施和核心层。所有层都使用依赖注入松散耦合。我想要实现的是,每当加载来自帐户表单(类库)的表单时,所有依赖项都应该加载到 UnityContainer 中,即注册的类型。这些依赖项是核心和基础设施项目中存在的接口和实现。

我的困惑是我应该在哪里编写代码来注册依赖项?这个应用程序的组合根是什么?请注意,来自 Accounts Forms、HR Forms 等的表单都是使用 Main Windows 应用程序中的反射加载的,该应用程序仅引用 Base Forms Project。

根据 Eben Roux 的建议

这是加载程序集时我执行wireup代码的方式:

 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

所以我现在的问题是:

  1. 将 Container 存储为 Shared 并使用它通过 Resolve 方法解决依赖关系是否正确?
  2. 我封装容器的 Resolve 行为的方式存在问题。什么是正确的语法?我不想在每个表单上引用 Unity 以便能够调用 Resolve 方法,所以我封装了我自己的 Resolve 方法。通过这种方式,如果我想更改 IOC 容器而不更改容器引用,我可以很容易地用另一个替换 AccountModule。
4

1 回答 1

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);
    }
}

我希望这是有道理的。

更新

首先,我会使用安全演员表。 TryCast在 VB.NET 世界中。您可以通过使用自己的界面,使用依赖反转从实际插件中摆脱 Unity。像这样:

public interface IDependencyContainer
{
    void Register(Type type);
    void Register<T>();
    void Resolve(Type type);
    void Resolve<T>();
}

好吧,你会添加你需要的东西。然后像我在 top 中所做的那样,传递对接线中容器的引用public void WireUp(IContainer container);

这种Resolve行为有些问题,因为您似乎正朝着服务定位器的方向前进。尝试通过使用构造函数(或其他)注入来尽可能多地由容器完成解析。当然,这对Singleton组件很有效。对于瞬态的,我宁愿使用接收一个实例的单例IDependencyContainer工厂(这样也将被注册),它会为你解决(实际上是创建)。

于 2014-01-03T05:09:35.700 回答