私は次の拡張メソッドを持っています。これは(当然のことながら)静的クラスに存在します。
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にならないようにするには、何が必要ですか?
すでに述べたように、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を介して解決するために使用されるファクトリデリゲートになります。