正如标题所述,我正在尝试使用与NHibernate 5.2.6集成的Autofac 4.9.4向实体中注入一些依赖项(例如域服务)。假设我们要将IPasswordHasher
doamin服务注入UserAccount
实体:
示例
public class UserAccount
{
public virtual Guid Id { get; set; }
public virtual string EMail { get; set; }
public virtual string HashedPassword { get; set; }
private readonly IPasswordHasher _passwordHasher { get; set; }
protected UserAccount() { }
public UserAccount(IPasswordHasher passwordHasher)
{
_passwordHasher = passwordHasher;
}
public virtual void SetCredentials(
string email, string plainTextPassword)
{
EMail = email;
SetPassword(plainTextPassword);
}
public virtual void SetPassword(string plainTextPassword)
{
HashedPassword = _passwordHasher.HashPassword(
EMail, plainTextPassword);
}
}
我已经读过this article,但不幸的是,这篇文章过时且对我来说很模糊。在最后一次尝试中,我尝试使用NHibernate.Cfg.Environment.BytecodeProvide
NuGet包设置Autofac.Extras.NHibernate,如下所示:
使用Autofac.Extras.NHibernate
ContainerBuilder builder = new ContainerBuilder();
//Bootstrap the Autofac container
builder.RegisterType<PasswordHasher>().As<IPasswordHasher>();
builder.RegisterType<UserAccount>().AsSelf();
builder.RegisterType<StaticProxyFactoryFactory>().As<IProxyFactoryFactory>();
builder.RegisterType<DefaultCollectionTypeFactory>().As<ICollectionTypeFactory>();
builder.RegisterType<AutofacBytecodeProvider>().As<IBytecodeProvider>();
var container = builder.Build();
//Assign the BytecodeProvider to NHibernate
NHibernate.Cfg.Environment.BytecodeProvider = container.Resolve<IBytecodeProvider>();
Configuration nhConfig = new Configuration().Configure();
ConfigNHibernateAndAddMappings(nhConfig );
var SessionFactory = nhConfig.BuildSessionFactory();
var session = SessionFactory.OpenSession();
//entity._passwordHasher dependency is null when NHibernta warpped it with proxy
var entity= session.Query<UserAccount>().Where(x => x.EMail == "[email protected]").FirstOrDefault();
问题当没有延迟加载时,NHibernate不会使用代理扭曲查询的实体,因此在这种情况下,依赖项将被成功注入。但是当NHibernate使用代理使实体变形时,依赖项将不会被注入并保持未初始化状态,有什么建议吗?
您不应将依赖项注入到聚合根中。
您可以使用double dispatch,但如今我更倾向于将值从应用程序/集成层(关注)传递给域对象。
而不是:
public virtual void SetCredentials(
string email, string plainTextPassword)
{
EMail = email;
SetPassword(plainTextPassword);
}
public virtual void SetPassword(string plainTextPassword)
{
HashedPassword = _passwordHasher.HashPassword(
EMail, plainTextPassword);
}
我会选择:
public virtual void SetCredentials(
string email, byte[] passwordHash)
{
EMail = email;
Password = passwordHash;
}
甚至更好的是将其作为构造函数。
您的应用程序服务将使用traditional依赖项注入来注入散列实现,而您的数据访问实现将不需要考虑依赖项。
这与@Yacoub Massad的建议一致。这将使您的生活比双倍调度更为简单。