Unity依赖注入报错:无法构造IPersonnelBusiness接口,求解决方案
嘿,我看了你的代码和报错信息,马上就发现了核心问题——这是Unity容器配置里一个很容易踩的小坑:
问题根源
在UnityConfig.RegisterTypes方法里,你重新实例化了一个新的UnityContainer,直接覆盖了方法传入的容器参数:
public static void RegisterTypes(IUnityContainer container) { // 这里的问题!你创建了一个新容器,替换了原本传入的那个 container = new UnityContainer(); // ... 后面的注册都是在这个新容器里做的 }
而UnityConfig里的Container属性引用的是一开始通过Lazy<IUnityContainer>创建的那个容器,和你在RegisterTypes里新建的容器完全是两个对象。这就导致:
- 你所有的接口映射(比如
IPersonnelBusiness → PersonnelBusiness)都注册到了那个没人用的新容器里 - 而
UnityMvcActivator里用来设置DependencyResolver的是UnityConfig.Container,这个容器里根本没有任何你的业务层接口注册,所以当HomeController需要解析IPersonnelBusiness时,Unity自然会报错说找不到映射。
另外,你还在RegisterTypes里重复设置了DependencyResolver,这也是多余的——UnityMvcActivator已经在应用启动时完成了这个操作,而且用的是正确的容器实例。
修复步骤
1. 移除多余的容器实例化
删掉RegisterTypes里的container = new UnityContainer();这行代码,直接使用方法传入的容器对象来注册类型。
2. 移除重复的DependencyResolver设置
把DependencyResolver.SetResolver(new UnityDependencyResolver(container));从RegisterTypes里删除,因为UnityMvcActivator已经在Start方法里用UnityConfig.Container设置了正确的依赖解析器。
3. (可选)清理HomeController的无参构造函数
虽然这不是当前报错的直接原因,但保留无参构造函数可能会让Unity优先选择它,导致依赖注入失效。如果你的HomeController完全依赖注入,建议删掉无参构造函数:
// 删掉这个无参构造 // public HomeController() { }
修复后的UnityConfig代码
public static class UnityConfig { #region Unity Container private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => { var container = new UnityContainer(); RegisterTypes(container); return container; }); /// <summary> /// Configured Unity Container. /// </summary> public static IUnityContainer Container { get { return container.Value; } } #endregion /// <summary> /// Registers the type mappings with the Unity container. /// </summary> /// <param name="container">The unity container to configure.</param> /// <remarks> /// There is no need to register concrete types such as controllers or /// API controllers (unless you want to change the defaults), as Unity /// allows resolving a concrete type even if it was not previously /// registered. /// </remarks> public static void RegisterTypes(IUnityContainer container) { // NOTE: To load from web.config uncomment the line below. // Make sure to add a Unity.Configuration to the using statements. // container.LoadConfiguration(); // TODO: Register your type's mappings here. // container.RegisterType<IProductRepository, ProductRepository>(); // 移除了container = new UnityContainer();这行 // Identity managment container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager()); container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager()); container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new HierarchicalLifetimeManager()); container.RegisterType<AccountController>(new InjectionConstructor()); container.RegisterType<PersonnelController>(new InjectionConstructor()); container.RegisterType<UsersAdminController>(new InjectionConstructor()); // Business Layer container.RegisterType<ILogBusiness, LogBusiness>(); container.RegisterType<IAnomalyBusiness, AnomalyBusiness>(); container.RegisterType<ICockpitStatBusiness, CockpitStatsBusiness>(); container.RegisterType<IDocumentBusiness, DocumentBusiness>(); container.RegisterType<IEmailBusiness, EmailBusiness>(); container.RegisterType<IMessageBusiness, MessageBusiness>(); container.RegisterType<INatureBusiness, NatureBusiness>(); container.RegisterType<IPersonnelBusiness, PersonnelBusiness>(); container.RegisterType<ISAPBusiness, SAPBusiness>(); // 移除了重复的DependencyResolver设置 } }
为什么升级Unity后才出现这个问题?
你提到之前因为堆栈溢出升级到了最新Unity,并且改成了延迟加载模式。延迟加载下,容器的初始化时机变了——原本可能在应用启动时就创建了容器,而现在是第一次访问UnityConfig.Container时才初始化。这就导致你之前隐藏的“容器实例不统一”的问题被暴露了出来,之前可能因为容器初始化顺序的巧合没触发这个错误。
按照上面的步骤修改后,你的依赖注入应该就能正常工作了!
内容的提问来源于stack exchange,提问作者clement

