9

“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
}

当我连接课程时,我这样做了:

builder.RegisterType<EmployeeFactory>()
       .As<IEmployeeFactory>().UsingConstructor(new ParameterlessConstructorSelector())
       .SingleInstance();

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

谢谢

4

3 回答 3

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;
    }
}

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

public class MyClass
{
    public readonly int i;

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

    public MyClass()
    {
        i = 1;
    }
}

随着您的实施:

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);

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

通过我的实现:

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

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

于 2012-12-21T14:42:57.970 回答
2

显式注册默认构造函数不是更简单吗?

builder.Register<EmployeeFactory>(c => new EmployeeFactory())
   .As<IEmployeeFactory>()
   .SingleInstance();
于 2012-12-21T15:16:51.100 回答
2

使用最新版本的 Autofac,这非常简单:

builder.RegisterType<EmployeeFactory>()
        .As<IEmployeeFactory>().UsingConstructor()
        .SingleInstance();

不带参数调用“UsingConstructor”意味着“使用无参数构造函数”。请参阅https://autofac.org/apidoc/html/EB67DEC4.htm和相关页面。

于 2017-05-29T10:14:57.513 回答