ASP.NET MVC中StructureMap依赖注入构造函数未触发问题咨询
兄弟,我刚看完你的问题,这情况我之前帮人排查过好几次,大概率是StructureMap的构造函数选择逻辑或者控制器工厂的小细节没处理好,咱们一步步来捋:
1. 控制器构造函数的优先级问题
StructureMap默认会优先选择参数最多的构造函数,但如果你的控制器同时存在无参构造函数和带依赖的构造函数,有时候会因为容器无法解析某个依赖(哪怕你觉得已经注册了),它会悄悄 fallback到无参构造函数,而且还不抛出任何错误——这坑我当初踩过好几次!
解决办法:
- 最直接的:删掉无参构造函数,这样StructureMap就只能尝试用带依赖的那个构造函数,要是依赖真的没注册对,会直接抛出异常,方便你快速定位问题;
- 如果你必须保留无参构造,就给带依赖的构造函数加上
[StructureMap.DefaultConstructor]特性,明确告诉StructureMap优先用这个:public class DemoController : Controller { private readonly IDemoBL _demoBL; [StructureMap.DefaultConstructor] public DemoController(IDemoBL demoBL) { _demoBL = demoBL; } // 必须保留的话就加上面的特性 public DemoController() { } }
2. 确保StructureMap能识别并解析控制器
你目前的代码里只注册了业务逻辑层的依赖,但没明确告诉StructureMap要处理控制器实例。旧版StructureMap不会自动扫描注册控制器,这会导致它无法正确创建带依赖的控制器,只能用默认的无参构造。
修改你的初始化代码,加上控制器扫描:
public class SiteConfig { public static void BootStrap() { ObjectFactory.Initialize(x => { x.AddRegistry<fullpath.BusinessRegistry>(); // 扫描包含控制器的程序集,自动注册所有控制器 x.Scan(scanner => { scanner.AssemblyContainingType<DemoController>(); // 替换成你的任意控制器类型 scanner.AddAllTypesOf<IController>(); }); }); ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory()); } }
另外,建议换成更可靠的非静态容器用法(避免静态类的生命周期问题):
public class StructureMapControllerFactory : DefaultControllerFactory { private readonly IContainer _container; public StructureMapControllerFactory(IContainer container) { _container = container; } public override IController CreateController(RequestContext requestContext, string controllerName) { var controllerType = base.GetControllerType(requestContext, controllerName); return controllerType == null ? null : _container.GetInstance(controllerType) as IController; } } public class SiteConfig { public static void BootStrap() { var container = new Container(x => { x.AddRegistry<fullpath.BusinessRegistry>(); x.Scan(scanner => { scanner.AssemblyContainingType<DemoController>(); scanner.AddAllTypesOf<IController>(); }); }); ControllerBuilder.Current.SetControllerFactory(new StructureMapControllerFactory(container)); } }
3. 验证业务层依赖是否真的能被解析
你注册了For<IDemoBL>().Use<DemoBL>(),但要确保DemoBL本身没有未注册的依赖!比如如果DemoBL的构造函数还依赖其他接口,你没在BusinessRegistry里注册,那StructureMap解析IDemoBL时会失败,这时候它就会退而求其次用控制器的无参构造。
快速验证方法:在BootStrap里手动解析一次IDemoBL,看会不会报错:
// 旧版ObjectFactory用法 var demoBL = ObjectFactory.GetInstance<IDemoBL>(); // 新版容器用法 var demoBL = container.GetInstance<IDemoBL>();
如果这行代码抛出异常,先把DemoBL的依赖问题解决再说。
4. 确认AngularJS请求的路由正确
最后再检查一下:AngularJS的$http请求的路由是不是真的指向了你配置了DI的控制器?有没有可能路由配置错了,导致实际调用的是另一个同名控制器,或者默认的控制器模板?
比如确认/Demo/YourAction对应的确实是你写的带DI的DemoController。
最常见的原因就是:要么控制器有多个构造函数,StructureMap因依赖解析问题 fallback到无参;要么控制器没被StructureMap扫描注册,导致它只能用默认逻辑创建实例。先试试删掉无参构造函数,看会不会抛出异常,这是最快定位问题的办法。
内容的提问来源于stack exchange,提问作者shivani surana

