3

私はautofac(2.1.14.854を使用)が初めてで、理解しようとしてまだ頭を動かそうとしています

インターフェイスがあり、このインターフェイスには 1 つ以上の実装があり、実装は特定の順序で起動する必要があります。

例えば:

public IPipeline
{ 
void execute(); 
}


public MyPipeLine_1:IPipeline
{
public void execute(){}
}

public MyPipeLine_2:IPipeline
{
public void execute(){}
}

foreach(IPipeline pipeline in pipelines)
          pipeline.execute(); 

IPipeline の注文実行は、MyPipleLine_2、MyPipleLine_1 などにする必要があります。

2 つの質問があります。1) アセンブリに IPipeLine インターフェイスを実装し、リストに配置するすべてのコンポーネントを登録する方法 2) 登録中にこれらのコンポーネントの実行順序を定義できます

前もって感謝します。

4

2 に答える 2

2

[簡単なメモ: 本当に古いバージョンの 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 登録を変更するだけです。

于 2013-03-11T15:11:27.103 に答える
1

メタデータ機能を使用することをお勧めします。登録段階で順序を定義できるという利点があります。

次に例を示します。

internal class Program
{
    private static void Main(string[] args)
    {
        var builder = new ContainerBuilder();
        var s1 = "First";
        var s2 = "Second";
        var s3 = "Third";
        builder.RegisterInstance(s1).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 1));
        builder.RegisterInstance(s2).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 2));
        builder.RegisterInstance(s3).As<string>().WithMetadata<Order>(c => c.For(order => order.OrderNumber, 3));

        using (var container = builder.Build())
        {
            var strings = container.Resolve<IEnumerable<Meta<string, Order>>>();
            foreach (var s in strings.OrderBy(meta => meta.Metadata.OrderNumber))
            {
                Console.WriteLine(s.Value);
            }
        }
        Console.ReadKey();
    }

    public class Order
    {
        public int OrderNumber { get; set; }
    }
}
于 2013-03-14T19:39:31.717 に答える