![](/img/trans.png)
[英]How can I create a keyed registration which ignores decorators in Autofac?
[英]Autofac ignores registration conflicts
我有以下測試
[TestFixture]
public class Test
{
public interface IMy { }
class MyClass : IMy { }
class MyClass2 : IMy { }
[Test]
public static void Go()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyClass>().AsImplementedInterfaces();
builder.RegisterType<MyClass2>().AsImplementedInterfaces();
var container = builder.Build();
var resolved = container.Resolve<IMy>();
Console.WriteLine(resolved);
}
}
為什么當實現明顯沖突時它不會拋出異常? 如果發現這樣的沖突,如何使它拋出異常?
注冊檢查的UPDATE解決方案幾乎沒問題,但是失敗的情況很簡單:
[TestFixture]
public class Test
{
public interface IPlugin
{
}
public interface IMy
{
}
class MyClass : IMy, IPlugin
{
public void Dispose()
{
}
}
class MyClass2 : IPlugin
{
public void Dispose()
{
}
}
public class SingleRegistrationModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
foreach (var service in registration.Services)
{
var registrations = componentRegistry.RegistrationsFor(service);
if (registrations.Count() > 1)
{
throw new Exception(
"Can't register '{registration.Activator.LimitType}' as '{service}'" +
" because '{registrations.First().Activator.LimitType}' is already registered");
}
}
}
}
[Test]
public static void Go()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyClass>().AsImplementedInterfaces();
builder.RegisterType<MyClass2>().AsImplementedInterfaces();
builder.RegisterModule<SingleRegistrationModule>();
var container = builder.Build();
var resolved = container.Resolve<IMy>();
Console.WriteLine(resolved);
}
}
在這種情況下,沒有人解析IInitializable,因此可以接受多個實現。 此外,有些情況下mulltiple實現正常,例如IPluginToSomething
Autofac不會拋出異常的原因是因為Autofac認為同一接口的多個注冊是集合的一部分。 例:
builder.RegisterType<MyClass>().As<IMy>();
builder.RegisterType<MyClass2>().As<IMy>();
var container = builder.Build();
var collection = container.Resolve<IEnumerable<IMy>>();
Console.WriteLine(collection.Count()); // prints "2"
如果進行多次注冊,調用Resolve<IMy>()
將只解析其中一個(第一個或最后一個,但我總是忘記它是哪一個)。 我個人認為這是Autofac(以及其他DI容器)中的設計缺陷,因為這會導致應用程序無聲地失敗,而不是快速失敗。 在簡單的噴油器的選擇,已作出嚴格區分藏品的登記(如解釋在這里 ),以防止這些類型的配置錯誤。
正如Steven所說, Autofac將考慮將同一服務的多個注冊作為集合的一部分。
如果您不想要此行為,可以使用Autofac模塊添加檢查:
public class SingleRegistrationModule : Module
{
protected override void AttachToComponentRegistration(
IComponentRegistry componentRegistry,
IComponentRegistration registration)
{
foreach (var service in registration.Services)
{
var registrations = componentRegistry.RegistrationsFor(service);
if (registrations.Count() > 1)
{
throw new Exception(
$"Can't register '{registration.Activator.LimitType}' as '{service}'" +
$" because '{registrations.First().Activator.LimitType}' is already registered");
}
}
}
}
然后您可以使用以下方式注冊模塊:
builder.RegisterModule<SingleRegistrationModule>();
構建容器時將拋出異常。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.