2015-06-24 30 views
0

我在Mono上使用Autofac 3.5.2,当我尝试注册一个泛型集合然后解决它时,我得到正确的实例,其中已经添加了一个正确类型的元素。要在代码中解释它:为什么解析集合还创建1个元素?

class Fake {} 

var builder = new ContainerBuilder(); 
builder.RegisterType<Fake>(); 
bilder.RegisterGeneric(typeof(List<>)); 

var scope = builder.Build(); 

var list = scope.Resolve<List<Fake>>(); 

Console.WriteLine(list.Count); // => prints 1! 

这是预期的吗?为什么?我怎样才能避免这种情况?

回答

1

Autofac has built-in support for collection并且默认情况下会尝试在解析服务时使用具有最多可用参数的构造函数。

Autofac自动使用与能够从容器
> http://autofac.readthedocs.org/en/latest/register/registration.html#register-by-type

List<T>获得的大多数参数为你的类的构造函数中包含一个构造函数,采取IEnumerable<T>。 当Autofac决心List<Fake>它会选择IEnumerable<T>构造函数,然后解决IEnumerable<T>这将解决所有可用实例T

如果你有一个以上的注册FakeAutofac当你解决将解决所有的人。例如:

var builder = new ContainerBuilder(); 
builder.RegisterType<Fake1>().As<IFake>(); 
builder.RegisterType<Fake2>().As<IFake>(); 
builder.RegisterGeneric(typeof(List<>)); 

var scope = builder.Build(); 

var list = scope.Resolve<List<IFake>>(); 
Console.WriteLine(list.Count); // => prints 2! 

您可以指定当您注册List<T>

var builder = new ContainerBuilder(); 
builder.RegisterType<Fake1>().As<IFake>(); 
builder.RegisterType<Fake2>().As<IFake>(); 
builder.RegisterGeneric(typeof(List<>)).UsingConstructor(Type.EmptyTypes); 

var scope = builder.Build(); 

var list = scope.Resolve<List<IFake>>(); 

Console.WriteLine(list.Count); // => prints 0! 

或者您也可以通过在Build方法

var builder = new ContainerBuilder(); 
builder.RegisterType<Fake1>().As<IFake>(); 
builder.RegisterGeneric(typeof(List<>)); 

var scope = builder.Build(ContainerBuildOptions.ExcludeDefaultModules); 

var list = scope.Resolve<List<IFake>>(); 
Console.WriteLine(list.Count); // => prints 0! 

使用ContainerBuildOptions.ExcludeDefaultModules参数忽略默认行为要使用的构造除非你真的知道你在做什么,否则我不会推荐删除默认行为。

+0

我会反过来。我会改变Autofac的默认配置,让它只使用一个公共构造函数来解析类型[以防止常见错误和不良设计](https://www.cuttingedge.it/blogs/steven/pivot/entry.php?id = 97),除非你真的知道你做了什么。 – Steven

相关问题