Asp.net mvc 如何禁用或防止Autofac踢入不需要的位置?
我有一个带有默认构造函数和DI构造函数的控制器:Asp.net mvc 如何禁用或防止Autofac踢入不需要的位置?,asp.net-mvc,autofac,Asp.net Mvc,Autofac,我有一个带有默认构造函数和DI构造函数的控制器: #if PROTOTYPING public class MyPrototypeController : Controller { MyRandomDataGeneratorComponent generatorSeededTheWayINeed; public MyPrototypeController() : this(new MyRandomDataGeneratorComponent(DateTime.No
#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
containerBuilder.Register(c => new MyController())
.AsSelf();
我希望通过调用默认构造函数来创建控制器。然而,Autofac认为它非常聪明,它竭尽全力使用参数化构造函数,但它无法创建MyRandomDataGeneratorComponent,因为它无法解析数字
天知道这有多烦人
我如何告诉此框架使用默认构造函数,或者完全禁用此控制器的默认构造函数?Autofac选择它知道如何解决的依赖关系最多的构造函数。似乎注册了
MyComponent
,但注册不正确:您没有指定someNumber
应该是什么。换句话说,如果您只是尝试Resolve()
您也会遇到同样的问题-MyController
不是这里的根本问题
有几种方法可以解决这个问题。最简单的方法是向MyComponent添加默认构造函数
public MyComponent() : this(DateTime.Now.Millisecond) { }
第二个最简单的方法是调整MyComponent
注册
containerBuilder.Register(c => new MyComponent(DateTime.Now.Milliseconds))
.AsSelf();
您也可以这样编写注册,以显式使用默认构造函数:
#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
containerBuilder.Register(c => new MyController())
.AsSelf();
您还可以更改代码,使MyComponent
根本不向Autofac注册,然后Autofac将不会选择MyController(MyComponent组件)
构造函数,但这似乎不是最佳解决方案
编辑
这些测试表明,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;
}
}
公共类MyController
{
MyRandomDataGenerator组件生成器需要每日更新;
公共MyController()
:此(新的MyRandomDataGeneratorComponent(DateTime.Now.毫秒)
/*不管是什么种子,我都不在乎*/)
{
}
公共MyController(MyRandomDataGenerator组件生成器需要每日更新)
{
/*为了测试的目的,我需要能够重现相同的随机情况*/
this.generatorseedthewayineed=generatorseedthewayineed;
}
}
公共类MyRandomDataGeneratorComponent
{
公共MyRandomDataGeneratorComponent(Int32 randomSeed)
{
/*使用种子初始化随机生成器*/
}
}
[测试方法]
公共无效示例1()
{
var cb=新的ContainerBuilder();
cb.RegisterType().AsSelf();
var container=cb.Build();
Assert.IsFalse(container.IsRegistered());
//由于MyRandomDataGeneratorComponent未注册,
//使用默认构造函数
var instance=container.Resolve();
}
[测试方法]
[ExpectedException(类型(Autofac.Core.DependencyResolutionException))]
公共无效示例2()
{
var cb=新的ContainerBuilder();
cb.RegisterType().AsSelf();
cb.RegisterType().AsSelf();
var container=cb.Build();
Assert.IsTrue(container.IsRegistered());
//由于MyRandomDataGeneratorComponent已注册,Autofac
//使用该构造函数,但无法解析参数“randomSeed”
尝试
{
var instance=container.Resolve();
}
捕获(Autofac.Core.dependencResolutionException ex)
{
Assert.IsTrue(例如Message.Contains(
“无法解析参数'Int32 randomSeed'”);
投
}
}
他们在上面回答了nemesv给你的答案:
Register(c=>newmycontroller()).AsSelf();是Autofac中的“切换到手动模式”。使用它,它将在不更改类的情况下工作
.AsSelf()是您需要的。MyComponent未在Autofac注册。请不要建议我更改类以使Autofac正常工作。我确信这是一个必须围绕我的需求的框架,而不是相反。无法关闭或切换到手动模式表明框架设计不当。@bonomo第三个示例:
vontainerBuilder.Register(c=>new MyController()).AsSelf()代码>是Autofac中的“切换到手动模式”。如果异常显示“无法解析MyComponent的参数'someNumber',则MyComponent已注册。(否则异常会说“MyComponent未注册”)也许您正在使用“任何尚未注册的具体类型”源?我发誓MyComponent未注册。这就是我添加默认构造函数的原因,因为我不想麻烦注册,我希望使用默认构造函数创建控制器不会有问题,即使组件没有注册。问题是,组件是一个临时的东西,只用于开发目的(模拟),它将离开生产代码。这就是为什么我希望它尽可能少地参与,仍然能够为测试目的注入它?这是一个。如果Autofac尝试创建MyComponent,则表示MyComponent已在您的容器中注册。你的评论表明情况并非如此。您的场景的真实状态是什么?如果该组件不在您的容器中,我相信Autofac会选择默认构造函数,因为它不“知道”MyComponent。@Steven,我添加了默认构造函数,因为我不想麻烦注册,我希望使用默认构造函数,即使组件没有注册,创建控制器也不会有问题。问题是,组件是一个临时的东西,只用于开发目的(模拟),它将离开生产代码。这就是为什么我希望它尽可能少地参与,仍然能够将它注入到