如何在NHibernate 5.x集成Autofac 4.x时为实体注入依赖?
解决NHibernate懒加载代理下Autofac依赖注入失效的问题
这个问题我之前也碰到过——NHibernate懒加载生成代理时,实体的构造函数依赖没被Autofac注入,非懒加载反而正常。核心原因是NHibernate默认用无参构造函数创建代理实例,且没让Autofac参与代理的依赖注入流程,下面是具体的解决步骤:
1. 修正AutofacBytecodeProvider的注册方式
AutofacBytecodeProvider需要依赖ILifetimeScope来解析容器中的服务,直接用RegisterType是不对的,要改成通过lambda注入容器实例:
using Autofac; using Autofac.Extras.NHibernate; using NHibernate.Cfg; var builder = new ContainerBuilder(); // 注册你的领域服务 builder.RegisterType<PasswordHasher>().As<IPasswordHasher>().InstancePerDependency(); // 注册实体 builder.RegisterType<UserAccount>().AsSelf(); // 关键:正确注册AutofacBytecodeProvider,传入容器的生命周期作用域 builder.Register(c => new AutofacBytecodeProvider(c.Resolve<ILifetimeScope>())) .As<IBytecodeProvider>() .SingleInstance(); var container = builder.Build();
2. 让NHibernate明确使用Autofac字节码提供者
不要直接设置静态的Environment.BytecodeProvider,而是在NHibernate配置中通过属性指定,确保配置加载时就生效:
var nhConfig = new Configuration(); // 告诉NHibernate使用Autofac的字节码提供者 nhConfig.SetProperty(Environment.BytecodeProvider, "autofac"); // 加载你的映射和其他NHibernate配置 nhConfig.Configure(); // 如果用XML配置文件,确保文件里也设置了bytecode.provider="autofac" ConfigNHibernateAndAddMappings(nhConfig); var sessionFactory = nhConfig.BuildSessionFactory();
3. 配置NHibernate使用实体的带参构造函数
这是最关键的一步——默认情况下NHibernate会用无参构造函数实例化实体(包括代理),导致依赖无法注入。你需要在映射中指定使用带IPasswordHasher参数的构造函数:
如果用Fluent NHibernate映射
using FluentNHibernate.Mapping; public class UserAccountMap : ClassMap<UserAccount> { public UserAccountMap() { Id(x => x.Id); Map(x => x.EMail); Map(x => x.HashedPassword); // 指定使用带IPasswordHasher参数的构造函数 ConstructorSelector<IPasswordHasher>(); } }
如果用XML映射
<class name="YourNamespace.UserAccount"> <id name="Id" type="Guid"> <generator class="guid.comb"/> </id> <property name="EMail"/> <property name="HashedPassword"/> <!-- 配置构造函数注入 --> <constructor> <param name="passwordHasher" type="YourNamespace.IPasswordHasher"/> </constructor> </class>
4. 移除多余的代理工厂注册
之前你手动注册的StaticProxyFactoryFactory和DefaultCollectionTypeFactory是多余的,AutofacBytecodeProvider会自动处理这些组件,删掉它们避免冲突:
// 删掉这两行! // builder.RegisterType<StaticProxyFactoryFactory>().As<IProxyFactoryFactory>(); // builder.RegisterType<DefaultCollectionTypeFactory>().As<ICollectionTypeFactory>();
为什么这样能解决问题?
- 修正后的
AutofacBytecodeProvider持有了容器的作用域,能在NHibernate创建实体/代理时从容器中解析依赖; - 配置NHibernate使用带参构造函数后,无论是直接加载实体还是生成懒加载代理,NHibernate都会调用带
IPasswordHasher的构造函数,Autofac会自动注入所需的依赖; - 去掉多余的代理工厂注册,确保Autofac完全接管了字节码和代理的创建流程。
现在你再测试懒加载的场景,UserAccount中的_passwordHasher应该就能正常注入了。
内容的提问来源于stack exchange,提问作者Masoud Sedghi
相关产品推荐
相关产品推荐

