我有以下测试
[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);
}
}
为什么当实现明显冲突时它不会抛出异常?如果发现这样的冲突,如何使它抛出异常呢?
更新 注册检查的解决方案几乎没问题,但是 失败时情况很简单:
[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
答案 0 :(得分:4)
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容器)中的设计缺陷,因为这会导致应用程序无声地失败,而不是快速失败。在Simple Injector中,已经选择严格区分集合的注册(如here所述),以防止出现这些类型的配置错误。
答案 1 :(得分:1)
正如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>();
构建容器时将抛出异常。