1

ソリューション構造(一部)

これは、ソリューションが部分的にどのように見えるかです。

私は Winforms 環境で Onion Architecture を使用しているため、UI、インフラストラクチャ、およびコア層があります。すべてのレイヤーは、依存性注入を使用して疎結合されています。私が達成したいのは、Accounts Forms (クラス ライブラリ) などのフォームがロードされるたびに、そのすべての依存関係を UnityContainer にロードする必要があることです。つまり、タイプを登録します。これらの依存関係は、コア プロジェクトとインフラストラクチャ プロジェクトに存在するインターフェイスと実装です。

私の混乱は、依存関係を登録するコードをどこに書くべきかということです? このアプリケーションの構成ルートは何ですか? Accounts Forms、HR Forms などのフォームはすべて、Base Forms Project のみを参照するメイン 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

だから私の質問は今です:

  1. Container を Shared として保存し、それを使用して Resolve メソッドを介して依存関係を解決するのは正しいアプローチですか?
  2. コンテナの解決動作をカプセル化する方法に問題があります。そのための正しい構文は何でしょうか? Resolve メソッドを呼び出せるようにするために各フォームで Unity を参照したくないので、独自の 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);
    }
}

それが理にかなっていることを願っています。

更新

まず、安全なキャストを使用します。 TryCastVB.NET の世界で。依存関係 iversion を使用して、独自のインターフェイスを使用して実際のプラグインから Unity を取り除くことができます。そのようなもの:

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

まあ、必要なものを追加します。次に、上で行ったように、ワイヤーアップでコンテナーへの参照を渡しpublic void WireUp(IContainer container);ます。

Service Locatorの方向に向かっているように見えるという点で、このResolve動作には多少問題があります。コンストラクター (またはその他の) インジェクションを使用して、コンテナーによってできるだけ多くの解決が行われるようにしてください。もちろん、これはSingletonコンポーネントでは問題なく機能します。一時的なものについては、のインスタンスを受け取るシングルトンファクトリを使用したいと思います(したがって、それも登録されます)。解決 (実際には作成) を行います。IDependencyContainer

于 2014-01-03T05:09:35.700 に答える