[簡単なメモ: 本当に古いバージョンの Autofac を使用しています。私が話している機能を取得するには、更新が必要になる場合があります。]
最初の部分は簡単です。Autofac は暗黙的にサポートしていますIEnumerable<T>
。すべてのタイプを登録して解決するだけです:
var builder = new ContainerBuilder();
builder.RegisterType<MyPipeLine_1>().As<IPipeline>();
builder.RegisterType<MyPipeLine_2>().As<IPipeline>();
var container = builder.Build();
var containsAllPipelineComponents = container.Resolve<IEnumerable<IPipeline>>();
IEnumerable<T>
リストではなく、リストとして取得できる方がよいでしょうが、リストが必要な場合は、その登録を追加できます。
builder
.Register(c => new List<IPipeline>(c.Resolve<IEnumerable<IPipeline>>()))
.As<IList<IPipeline>>();
2番目の部分はそれほど簡単ではありません。Autofac は、必ずしもリスト内の項目の順序を保証しません。それらを順序付ける必要がある場合は、何らかの順序付けメタデータ (属性、プロパティ、後でパイプラインを順序付けるために使用できるもの) をそれらに配置する必要があります。
または、パイプラインにさまざまなコンポーネントを適用できる「ステージ」または「イベント」がある場合は、パイプラインの設計を調べて、イベントごとに異なるパイプライン インターフェイスを用意してください。イベント内では、各アイテムがどの順序で実行されるかは重要ではありません。特定の各ステージでは、ハンドラーの実行順序は重要ではありません。)
例は次のようになります。
public interface IFirstStage
{
void Execute();
}
public interface ISecondStage
{
void Execute();
}
public interface IThirdStage
{
void Execute();
}
public class PipelineExecutor
{
public IEnumerable<IFirstStage> FirstHandlers { get; private set; }
public IEnumerable<ISecondStage> SecondHandlers { get; private set; }
public IEnumerable<IThirdStage> ThirdHandlers { get; private set; }
public PipelineExecutor(
IEnumerable<IFirstStage> first,
IEnumerable<ISecondStage> second,
IEnumerable<IThirdStage> third)
{
this.FirstHandlers = first;
this.SecondHandlers = second;
this.ThirdHandlers = third;
}
public void ExecutePipeline()
{
this.ExecuteFirst();
this.ExecuteSecond();
this.ExecuteThird();
}
public void ExecuteFirst()
{
foreach(var handler in this.FirstHandlers)
{
handler.Execute();
}
}
// ExecuteSecond and ExecuteThird look just
// like ExecuteFirst, but with the appropriate
// set of handlers.
}
次に、ハンドラーを登録するのは簡単です。
var builder = new ContainerBuilder();
builder.RegisterType<SomeHandler>().As<IFirstStage>();
builder.RegisterType<OtherHandler>().As<IFirstStage>();
builder.RegisterType<AnotherHandler>().As<ISecondStage>();
// You can have any number of handlers for any stage in the pipeline.
// When you're done, make sure you register the executor, too:
builder.RegisterType<PipelineExecutor>();
パイプラインを実行する必要がある場合は、解決して実行します。
var executor = container.Resolve<PipelineExecutor>();
executor.ExecutePipeline();
これはイベント ハンドラーに似ていますが、デリゲートを使用していません。パイプラインの「イベント」または「ステージ」の順序は固定されていますが、各ステージ内のハンドラーの順序は保証されていません。
パイプラインを変更してステージを増やす必要がある場合は、コードを変更する必要があります。公開したい新しいイベントがあるかのように。ただし、ハンドラーを追加、削除、または変更するには、Autofac 登録を変更するだけです。