1

Autofacを使用していて、現在のアセンブリの正しい実装を解決したい

DataContextFactoryインターフェイスとクラスがあります。

Public Interface IDataContextFactory
  Inherits IDisposable

  Function GetDataContext() As IDataContext

End Interface

およびインターフェースの実装

Public Class CDataContextFactory
  Implements IDataContextFactory

  Private m_oDbContext As IDataContext

  Public Sub New(ByVal i_oDbContext As IDataContext)
    m_oDbContext = i_oDbContext
  End Sub

  Public Function GetDataContext() As CoreData.IDataContext Implements CoreData.IDataContextFactory.GetDataContext
    Return m_oDbContext
  End Function

End Class

これで、登録されたすべてのアセンブリに異なるIDataContext実装があります。たとえば、データコンテキストを持つReportDataというアセンブリがあります

Public Class CReportDataContext
  Inherits DbContext
  Implements IDataContext

    ---
End Class

また、他のAssemblyCommonData内の1つの実装

Public Class CFacadeDataContext
  Implements IDataContext

    ---
End Class

次に、すべてのアセンブリにIRepositoryの実装があります。例えば

Public MustInherit Class CBaseReadRepository(Of T As {IEntity, Class})
  Implements IReadRepository(Of T)

  Private m_oDataContextFactory As IDataContextFactory
  Private m_oDataContext As IDataContext

  Protected ReadOnly m_oObjectDataSet As CQuery(Of T)

  Public Sub New(ByVal i_oDataContextFactory As IDataContextFactory)
    m_oDataContextFactory = i_oDataContextFactory
    m_oObjectDataSet = DataContext.ObjectDataSet(Of T)()
  End Sub

    ----
End Class

では、DataContextFactoryがAssemblyReportData内のCReportDataContextとAssemblyCommonData内のCFacadeDataContextを解決することをどのように解決できますか?

これが私のContainerBuilder登録です:

Dim builder As New ContainerBuilder()

Dim oData = Assembly.Load("ReportData")
builder.RegisterAssemblyTypes(oData).Where(Function(t) t.Name.EndsWith("DataContext")).As(Of IDataContext) _
  .AsImplementedInterfaces.SingleInstance

oData = Assembly.Load("CommonData")
builder.RegisterAssemblyTypes(oData).Where(Function(t) t.Name.EndsWith("DataContext")) _
  .AsImplementedInterfaces().SingleInstance

builder.RegisterAdapter(Of IDataContext, IDataContextFactory)(Function(x) New CDataContextFactory(x))

ありがとう

4

1 に答える 1

1

Autofac には、この種のユース ケースに対するサポートが組み込まれていません。一般に、特定の実装をコンシューマーに関連付けないようにすることをお勧めします。これは、IoC パターン全体を壊すためです。必要な依存関係の型を、注入するのではなく、クラス内で「新規作成」することもできます。

どうしてもそれらを結び付けなければならない場合、いくつかのオプションしかありません。どちらもきれいではなく、どちらも登録方法を変更する必要があります。現在のRegisterAssemblyTypesようにアセンブリ スキャンを実行できない場合があります。

まず、名前付き登録を使用できます。を登録するときIDataContextに、名前を付けます。コンシューマー クラスを登録するときに、使用する名前付きインスタンスをビルダーに伝えます。

builder.RegisterType<MyDataContext>().Named<IDataContext>("some-name");
var contextParam = ResolvedParameter.ForNamed<IDataContext>("some-name");
builder.RegisterType<MyConsumer>().As<IConsumer>().WithParameter(contextParam);

次に、コンシューマの型ではなく式を登録できます。

builder.Register(c => new Consumer(new SomeContext())).As<IConsumer>();

最後に、コンシューマーがどのアセンブリから来ているかを判断し、それを対応するIDataContext. これはより「自動」ですが、はるかに複雑です。スタブは次のようになります。

public class DataContextModule : Autofac.Module
{
  protected override void AttachToComponentRegistration(
    IComponentRegistry componentRegistry,
    IComponentRegistration registration)
  {
    registration.Preparing += OnComponentPreparing;
  }

  public static void OnComponentPreparing(object sender, PreparingEventArgs e)
  {
    Type typeBeingResolved = e.Component.Activator.LimitType;
    // TODO: Do some reflection to determine if the type takes an IDataContext
    // in the constructor. If it doesn't, bail. If it does...

    var parameter = new ResolvedParameter(
      (p, i) => p.ParameterType = typeof(IDataContext),
      (p, i) => {
        // TODO: Use i (the IComponentContext for the resolution)
        // to locate the right IDataContext from the list of registrations,
        // resolve that one, and return it so it can be used in
        // constructing the consumer object.
      });
  }
}

私が言ったように、きれいではありません。

デザインに影響を与える能力がある場合は、次のようなマーカー インターフェイスを作成する方が簡単かもしれません。

public interface ICoreDataContext : IDataContext { }

そして、コンストラクターで特定のインターフェイスを取得します。

public SomeClass(ICoreDataContext context);

そうすれば、型解決が機能します。(マーカー インターフェースも世界で最も優れたパターンではありませんが、物事の個々の実装を特定の消費型に結び付けるよりは間違いなく優れています。)

于 2012-06-13T16:11:21.757 に答える