我有一个带默认构造函数和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,因为它无法解析数字。
上帝知道这有多烦人。
如何告诉此框架使用默认构造函数,还是可以完全禁用此控制器?
答案 0 :(得分:2)
他们回答上述nemesv给了你答案:
ContainerBuilder.Register(c => new MyController())。AsSelf();是Autofac中的“切换到手动模式”。使用它,它可以在不改变你的类的情况下工作。
.AsSelf()就是你要找的。 p>
答案 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;
}
}