web-dev-qa-db-ja.com

Unityで静的クラスの依存関係を解決するにはどうすればよいですか?

私は次の拡張メソッドを持っています。これは(当然のことながら)静的クラスに存在します。

public static class MyExtensions
{
    [Dependency]
    private static IMyDataContext _myDataContext { get; set; }

    public static void MyExtensionMethod(this MyType myType)
    {
        // do stuff

        _myDataContext.DoAwesomeThing();
    }
}

_myDataContextオブジェクトはnullです。

通常はUnityContainerを使用して型を登録しますが、これは静的クラスであるため、登録できません。

_myDataContextをインスタンス化して、必要なときにnullにならないようにするには、何が必要ですか?

16
DaveDev

すでに述べたように、Unityは静的であるため、クラスを解決するために使用することはできません。これにはいくつかのオプションがあります。私の個人的なお気に入りは、AbstractFactoryパターンを使用することです。 DIでうまく機能するように、パターンを少しだけ微調整する傾向があります。

工場は通常、次のようになります。

/// <summary>
/// Creates an IMyDataContext instance
/// </summary>
public static class MyDataContextFactory
{
    /// <summary>
    /// The factory used to create an instance
    /// </summary>
    static Func<IMyDataContext> factory;

    /// <summary>
    /// Initializes the specified creation factory.
    /// </summary>
    /// <param name="creationFactory">The creation factory.</param>
    public static void SetFactory(Func<IMyDataContext> creationFactory)
    {
        factory = creationFactory;
    }

    /// <summary>
    /// Creates a new IMyDataContext instance.
    /// </summary>
    /// <returns>Returns an instance of an IMyDataContext </returns>
    public static IMyDataContext CreateContext()
    {
        if (factory == null) throw new InvalidOperationException("You can not create a context without first building the factory.");

        return factory();
    }
}

bootstrapプロセス(サービス登録を設定する場所)では、ファクトリを初期化して依存関係を解決できます。

MyDataContextFactory.SetFactory(() => this.Container.Resolve<IMyDataContext>());

次に、拡張メソッドでコンテキストをフェッチします。

public static class MyExtensions
{
    public static void MyExtensionMethod(this MyType myType)
    {
        MyDataContextFactory.CreateContext().DoAwesomeThing();
    }
}

コンテキストのUnity登録は、サービスを解決するための条件がある場合、サービスのさまざまな異なる構成を処理できます。 Unity以外でコンテキストを設定できる可能性がある場合、その所有者は、拡張メソッドが使用する新しいデリゲートを渡すことができます。

コンテナー自体を工場に渡すことは避けがちです。これは、コンテナーがアプリに緊密に結合され始めているためです。ファクトリに何かを渡す場合は、DIコンテナ自体を渡すのではなく、DIを介して解決するために使用されるファクトリデリゲートになります。

20