示例代码:
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterSource(new RegistrationSource());
builder.RegisterType<Cmd1>().AsSelf().As<ICmd>();
IContainer container = builder.Build();
var cmds = container.Resolve<IEnumerable<ICmd>>();
RegistrationSource将提供Cmd2
类型,cmds
结果为cmd1
,cmd2
。但我想要Cmd2
,Cmd1
。
我该怎么做?
答案 0 :(得分:0)
如果RegistrationSource无法恢复组件,它将返回由RegisterType或其他解决方案提供的默认组件
RegistrationSource
不会返回任何内容。它只向组件注册表注册新注册。
我认为你想要的是当 Autofac 解决问题时,它会首先尝试使用RegistrationSource
提供的注册,如果没有,它应该尝试使用没有RegistrationSource
的注册。是对的吗 ?
这是不可能的。无论是否由RegistrationSource
提供,所有注册都是等效的。
但是,您可以注册许多名为IFoo
且只有一个IFoo
来选择要使用的正确名称IFoo
,而不是注册多个IFoo
。
builder.Register(c => c.ResolveNamed<IEnumerable<Meta<IFoo>>>("Ordered")
.OrderBy(metaFoo => (Int32)metaFoo.Metadata["order"])
.Select(metaFoo => metaFoo.Value)
.First())
.As<IFoo>();
// classic registration
builder.RegisterType<Foo1>()
.Named<IFoo>("Ordered")
.WithMetadata("order", 20);
// this registration can be provided by a RegistrationSource
builder.RegisterType<Foo2>()
.Named<IFoo>("Ordered")
.WithMetadata("order", 10);
现在 Autofac 会在结算order
IFoo
注册的IFoo
元数据
在澄清之前做出了以下回答
您可以使用PreserveExistingDefaults
方法将注册推送到注册列表的末尾。
builder.RegisterType<Foo1>().As<IFoo>();
builder.RegisterType<Foo2>().As<IFoo>().PreserveExistingDefaults();
// ...
container.Resolve<IEnumerable<IFoo>>() => Foo1, Foo2
在您的情况下,如果您想控制注册的顺序,我建议您使用meta进行操作。
builder.RegisterType<Foo1>().As<IFoo>().WithMetadata("order", 10);
builder.RegisterType<Foo2>().As<IFoo>().WithMetadata("order", 20);
builder.RegisterType<Foo3>().As<IFoo>().WithMetadata("order", 15);
// ...
IEnumerable<IFoo> foos = container.Resolve<IEnumerable<Meta<IFoo>>>()
.OrderBy(o => (Int32)o.Metadata["order"])
.Select(o => o.Value);
// foos => Foo1, Foo3, Foo2
如果您想更进一步,可以实施一个自定义IRegistrationSource
,为IOrderedEnumerable<T>
提供注册。每次您需要有序的可枚举时,您将能够解决IOrderedEnumerable<T>
并确保订单。