[快速说明:您使用的是非常旧的 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>>();
第二部分并不那么容易。Autofac 不一定保证列表中项目的顺序。如果您需要对它们进行排序,则需要在它们上放置某种排序元数据 - 属性、属性,这些东西可用于事后对管道进行排序。
或者,如果您的管道具有适用于不同组件的“阶段”或“事件”,请查看管道的设计并为每个事件提供不同的管道接口。在事件中,每个项目的执行顺序无关紧要。(这类似于 .NET 中的事件处理程序现在的工作方式。您希望模仿这种行为 - 整个生命周期中不同阶段的不同事件,但在每个特定阶段处理程序的执行顺序并不重要。)
一个示例可能如下所示:
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 注册。