如何禁用或阻止Autofac在不需要的地方踢?

时间:2013-07-15 19:51:27

标签: asp.net-mvc autofac

我有一个带默认构造函数和DI构造函数的控制器:

#if PROTOTYPING
public class MyPrototypeController : Controller
{
    MyRandomDataGeneratorComponent generatorSeededTheWayINeed;
    public MyPrototypeController()
        : this(new MyRandomDataGeneratorComponent(DateTime.Now.Millisecond)
        /* whatever seed, I don't care */) {
    }
    public MyPrototypeController(MyRandomDataGeneratorComponent generatorSeededTheWayINeed) {
        /* DI for testing purposes, I need to be able to reproduce the same random situation */
        this.generatorSeededTheWayINeed = generatorSeededTheWayINeed;
    }
}
public class MyRandomDataGeneratorComponent
{
    public MyRandomDataGeneratorComponent(Int32 randomSeed)
    {
        /* use the seed to initialized the random generator */
    }
}
#endif

我希望通过调用默认构造函数来创建控制器。然而,Autofac认为它非常聪明,它使用参数化构造函数,但它无法创建MyRandomDataGeneratorComponent,因为它无法解析数字。

上帝知道这有多烦人。

如何告诉此框架使用默认构造函数,还是可以完全禁用此控制器?

2 个答案:

答案 0 :(得分:2)

他们回答上述nemesv给了你答案:

ContainerBuilder.Register(c => new MyController())。AsSelf();是Autofac中的“切换到手动模式”。使用它,它可以在不改变你的类的情况下工作。

.AsSelf()就是你要找的。

答案 1 :(得分:1)

Autofac选择具有最多依赖关系的构造函数,它知道如何解析。似乎MyComponent已注册,但注册错误:您尚未指定someNumber应该是什么。换句话说,如果您刚试过Resolve<MyComponent>(),那么您会遇到同样的问题 - MyController不是根本问题。

有几种方法可以解决这个问题。最简单的方法是向MyComponent

添加默认构造函数
public MyComponent() : this(DateTime.Now.Millisecond) { }

第二个最简单的方法是调整MyComponent注册

containerBuilder.Register(c => new MyComponent(DateTime.Now.Milliseconds))
    .AsSelf();

您也可以像这样编写注册,以显式使用默认构造函数:

containerBuilder.Register(c => new MyController())
    .AsSelf();

您也可以更改代码,以便{Ent}完全没有注册MyComponent,然后Autofac将不会选择MyController(MyComponent component)构造函数,但这似乎不是最佳解决方案。< / p>

修改

这些测试表明MyRandomDataGeneratorComponent(又名MyComponent)实际上已注册。如果您需要帮助确定如何注册,请发布您的注册码。

public class MyController
{
    MyRandomDataGeneratorComponent generatorSeededTheWayINeed;
    public MyController()
        : this(new MyRandomDataGeneratorComponent(DateTime.Now.Millisecond)
            /* whatever seed, I don't care */)
    {
    }
    public MyController(MyRandomDataGeneratorComponent generatorSeededTheWayINeed)
    {
        /* DI for testing purposes, I need to be able to reproduce the same random situation */
        this.generatorSeededTheWayINeed = generatorSeededTheWayINeed;
    }
}
public class MyRandomDataGeneratorComponent
{
    public MyRandomDataGeneratorComponent(Int32 randomSeed)
    {
        /* use the seed to initialized the random generator */
    }
}

[TestMethod]
public void example1()
{
    var cb = new ContainerBuilder();
    cb.RegisterType<MyController>().AsSelf();
    var container = cb.Build();

    Assert.IsFalse(container.IsRegistered<MyRandomDataGeneratorComponent>());
    // since MyRandomDataGeneratorComponent is not registered,
    // the default constructor is used
    var instance = container.Resolve<MyController>();
}

[TestMethod]
[ExpectedException(typeof(Autofac.Core.DependencyResolutionException))]
public void example2()
{
    var cb = new ContainerBuilder();
    cb.RegisterType<MyController>().AsSelf();
    cb.RegisterType<MyRandomDataGeneratorComponent>().AsSelf();
    var container = cb.Build();

    Assert.IsTrue(container.IsRegistered<MyRandomDataGeneratorComponent>());
    // since MyRandomDataGeneratorComponent is registered, Autofac
    // uses that constructor, but cannot resolve parameter "randomSeed"
    try
    {
        var instance = container.Resolve<MyController>();
    }
    catch (Autofac.Core.DependencyResolutionException ex)
    {
        Assert.IsTrue(ex.Message.Contains(
            "Cannot resolve parameter 'Int32 randomSeed'"));
        throw;
    }
}