Autofac无参数构造函数选择

she*_*per 9 autofac

"Autofac会自动选择具有能够从容器中获取的最多参数的构造函数." 我希望它不这样做,而是选择默认构造函数.http://code.google.com/p/autofac/wiki/Autowiring

internal class ParameterlessConstructorSelector : IConstructorSelector
{
    #region Implementation of IConstructorSelector

    /// <summary>
    /// Selects the best constructor from the available constructors.
    /// </summary>
    /// <param name="constructorBindings">Available constructors.</param>
    /// <returns>
    /// The best constructor.
    /// </returns>
    public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
    {
        return constructorBindings.First();
    }

    #endregion
}
Run Code Online (Sandbox Code Playgroud)

当我上课时,我这样做了:

builder.RegisterType<EmployeeFactory>()
       .As<IEmployeeFactory>().UsingConstructor(new ParameterlessConstructorSelector())
       .SingleInstance();
Run Code Online (Sandbox Code Playgroud)

constructorBindings列表中的第一个绑定始终是带有paremeterless构造函数的绑定.不确定它是先定义还是autofac扫描构造函数的方式,但这是无参数构造函数的正确接线方法吗?

谢谢

nem*_*esv 7

Autofac在内部使用该Type.GetConstructors方法来发现构造函数.

从方法文档:

GetConstructors方法不以特定顺序返回构造函数,例如声明顺序.您的代码不能依赖于返回构造函数的顺序,因为该顺序会有所不同.

所以只是运气,它与First()你的情况一起工作.在正确的实现中,您需要显式搜索带有0个参数的构造函数:

public class DefaultConstructorSelector : IConstructorSelector
{
    public ConstructorParameterBinding SelectConstructorBinding(
        ConstructorParameterBinding[] constructorBindings)
    {
        var defaultConstructor = constructorBindings
          .SingleOrDefault(c => c.TargetConstructor.GetParameters().Length == 0);
        if (defaultConstructor == null)
            //handle the case when there is no default constructor
            throw new InvalidOperationException();                
        return defaultConstructor;
    }
}
Run Code Online (Sandbox Code Playgroud)

你可以用这个非常简单的类测试理论:

public class MyClass
{
    public readonly int i;

    public MyClass(int i)
    {
        this.i = i;
    }

    public MyClass()
    {
        i = 1;
    }
}
Run Code Online (Sandbox Code Playgroud)

随着您的实施:

var builder = new ContainerBuilder();
// register 22 for each integer constructor argument
builder.Register<int>(v => 22); 

builder.RegisterType<MyClass>().AsSelf()
    .UsingConstructor(new ParameterlessConstructorSelector());
var c = builder.Build();
var myClass = c.Resolve<MyClass>();
Console.WriteLine(myClass.i);
Run Code Online (Sandbox Code Playgroud)

它输出22例如带有int参数的构造函数:

随着我的实施:

//...
builder.RegisterType<MyClass>().AsSelf()
    .UsingConstructor(new DefaultConstructorSelector());
//...
var myClass = c.Resolve<MyClass>();
Console.WriteLine(myClass.i);
Run Code Online (Sandbox Code Playgroud)

它输出1例如调用默认构造函数.