假设我有一个通过ORM部分填充的User类,但是有一些与此实体逻辑相关的数据是从其他地方提供的。
public class User {
public int Id { get; set; }
public int ServiceId { get; set; }
public string FirstName => null; //this comes from somewhere else
public ICollection<Role> Roles { get; set; }
//etc...
}
以前,在类似的情况下,我一直允许IOC容器将单个接口注入到域模型中来处理这个问题。
public class User {
public readonly IUserBehavior _userBehavior;
public User() {}
public User(IUserBehavior userBehavior) {
_userBehavior = userBehavior;
}
public int Id { get; set; }
public int ServiceId { get; set; }
public string FirstName => _behavior?.getFirstName(this);
public ICollection<Role> Roles { get; set; }
//etc...
}
然而,我最近尝试从nHibernate切换到Entity Framework,这看起来使这变得不可能(至少,使用构造函数注入)。
我现在的选择似乎是移动服务调用(实现细节)以直接获取缺少的数据到实体中或使用看似相反的双重调度模式...该类型的某些数据属性必须以特殊的方式被召唤。如果这是一个改变状态的动作,我可以看到双重调度更有意义。或者,我想我可以回到nHibernate。
我想我所问的是我的任何选项实际上是“好”,还是有其他选择我应该考虑?
答案 0 :(得分:0)
使用装饰器提供必要的功能:https://en.wikipedia.org/wiki/Decorator_pattern
因此,从您的业务层(或您需要访问User
类的任何地方),您可以调用首先调用EF的装饰器类,然后使用您的自定义流程来提供FirstName
等。
答案 1 :(得分:0)
正如多人here,here和here所解释的那样,使用构造函数注入将依赖项注入实体并不是一个好主意。
相反,你使用方法注入要好得多。例如:
public class User {
public int Id { get; set; }
public int ServiceId { get; set; }
public ICollection<Role> Roles { get; set; }
public string GetFirstName(IUserBehavior behavior) => behavior.GetFirstName(this);
//etc...
}
这里,实体上的每个方法都定义了自己的依赖关系集,这些依赖关系是使用方法注入注入的。这使得实体上的方法非常可测试,并且无法使用容器来构建实体。
相反,使用服务将获得注入其构造函数的必需依赖项,并将这些依赖项传递给它调用的方法。
但是,在这种情况下,GetFirstName()
方法的行为非常简单,通过让服务调用behavior.GetFirstName(User)
本身可能更好。