1

サービスが相互に関連しているautofac登録の状況があります。これが私が今持っているものです:

var builder = new ContainerBuilder();

const string A = "A";
const string B = "B";

//Part 1
builder.RegisterType<ClassA1>().Named<IClass1>(A);
builder.RegisterType<ClassA2>().Named<IClass2>(A);

builder.RegisterType<ClassB1>().Named<IClass1>(B);
builder.RegisterType<ClassB2>().Named<IClass2>(B);

//Part 2
builder.Register(c => new ClassProcess(A, c.ResolveNamed<IClass1>(A), c.ResolveNamed<IClass2>(A))).Named<ClassProcess>(A).SingleInstance();
builder.Register(c => new ClassProcess(B, c.ResolveNamed<IClass1>(B), c.ResolveNamed<IClass2>(B))).Named<ClassProcess>(B).SingleInstance();

//Part 3
builder.Register(c => new ClassProcessDependency(c.ResolveNamed<ClassProcess>(B), c.ResolveNamed<ClassProcess>(A)));

パート1では、ペアで接続されている2つの基本クラス、IClass1とIClass2を定義します。

パート2では、これら2つのクラスを接続する「プロセス」を定義します。このプロセスは、IEnumerableを使用するプログラムの残りの部分に実際に渡されるものです。

パート3では、これらのプロセス間に存在する依存関係を定義して、正しい順序で実行されるようにします。

ここで探しているのは、以前にname / key / metaで登録されたサービスを使用し、そのデータを使用して新しいサービスを登録できるAutofacの登録メソッドです。

編集:これを行うためのAutofac固有の方法があるかどうかを調べようとしていることに注意してください。

4

1 に答える 1

3

列挙できるリストに定数があると仮定すると...

IEnumerable<string> constants

……できない理由があるの?

foreach(var constant in constants)
{
  // Careful of the closure...
  var loopItem = constant;
  builder
    .Register(c =>
      new ClassProcess(
        loopItem,
        c.ResolveNamed<IClass1>(loopItem),
        c.ResolveNamed<IClass2>(loopItem)))
    .Named<ClassProcess>(loopItem)
    .SingleInstance();
}

私が間違っていたり誤解していたり​​しない限り、あなたを妨げているのは、識別子定数のセットがまだリストにない場合だけです。これは Autofac がお手伝いできることではありません。

コード内で foreach を使用したくない場合は、いつでもモジュール内で非表示にすることができます。

public class ProcessModule : Autofac.Module
{
  private IEnumerable<string> _constants;
  public ProcessModule(IEnumerable<string> constants)
  {
    this._constants = constants;
  }

  protected override void Load(ContainerBuilder builder)
  {
    // Put the foreach here and loop over this._constants.
  }
}

次に、モジュールをメイン コードに登録します。

builder.RegisterModule(new ProcessModule(constants));

そのようにループできない場合は、自動化のアプローチが制限されている可能性があります。または、少なくとも、もっと複雑なものを見ていることになります。

では、登録されているアイテムのContainerBuilderセットに直接アクセスすることは実際には許可されていないため、もう少し低レベルのトリックを実行する必要があります。おそらくIRegistrationSource、特定のタイプのすべての名前付き登録を見つけて自動化するために を実装できます。

残念ながら、前述のように、このプロセスはもう少し複雑なので、ソリューション全体を書き出すつもりはありません。ただし、基本的に何が機能すると思われるかを説明し、ソースコードで例を確認するための参照をいくつか示します。

この道を歩み始める前に、Ni​​ck Blumhardt が彼のブログに素晴らしい記事を掲載しており、これらの 1 つを作成する方法を説明し、組み込みの Autofac ソースの 1 つを例として使用しています。

まず、 を実装するAutofac.Core.IRegistrationSource必要がありますこれは、暗黙的なコレクション サポートの追加などを行うために使用されるインターフェイスです (したがって、5 つのIFooインスタンスを登録すると解決できIEnumerable<IFoo>、機能します)。コア Autofac アセンブリの Autofac コードで登録ソースの例を確認できます。

登録ソースの主な機能は、ソースRegistrationsForによって生成された登録のリストを返すメソッドです。

IEnumerable<IComponentRegistration> RegistrationsFor(
  Service service,
  Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor);

このメソッドの実装は、着信serviceが...

  • An Autofac.Core.KeyedService(すべてのサービスに名前を付けているため) AND
  • あなたが期待するタイプの。

すべての惑星が整列している場合は、すべての設定が記入されたIComponentRegistrationfor を返します。ClassProcess

名前付きの2つの入力パラメーターが必要であり、すべてのパラメーターの依存関係も登録されていることを確認しない限りClassProcess、おそらく名前付きを登録したくないため、これはより困難になります。ClassProcess見たサービスを追跡し、ClassProcess入ってくるすべての依存関係を確認した場合にのみ登録します (入ってKeyedServiceくるサービスを使用して、サービスの名前が何であるかを把握できます)。

さらに、そのコンポーネントの登録を作成する作業はContainerBuilderもう行わないため、「有効期間」などに対応する登録の適切な設定をすべて把握する必要があります。

入手したら、IRegistrationSourceそれを に接続する必要がありますContainerBuilder

builder.RegisterSource(new MyRegistrationSource());

繰り返しますが、これを追求することに興味がある場合は、Autofac ツリーでこれらのソース ファイルを調べてください。複雑なため、多くの人がたどる道ではありません。

正直なところ...定数をループできるなら、私はそうします。これは、foreach ループを回避するためだけに、多くの作業を行うように思えます。

于 2012-06-13T16:23:30.810 に答える