我目前正在使用一个使用Anemic Domain Model的代码库,我正在尝试将更多逻辑转移到域模型中,转向域模型和域驱动设计,但我正在努力解决以下问题。
我有一个名为Job的域模型,看起来像这样,
public class Job
{
private DateTime _someOtherDate;
private DateTime _lastUpdated;
// this may be called from many different services
public void SetLastUpdated()
{
_lastUpdated = DateTime.UtcNow;
}
}
在某个时间点,在处理作业期间,我想将作业的上次更新日期设置为该特定时间点。要做到这一点,我已经为它创建了一个公共setter,如上所示。
当我从我的存储库中的数据库中撤回Job时出现问题,因为我现在没有该字段的公共setter,因为我已将其限制为SetLastUpdated()
。
有人可以告诉我如何在检索作业时允许在存储库实现中设置此属性,但不能从仅限于调用SetLastUpdated()
的服务中设置。
更新1)我已经更新了问题,因为使用开始日期是个不错的例子。
更新2)从给出的答案中,我可以看到完成此操作的唯一方法是不在存储库中使用AutoMapper,在Job类中添加构造函数以设置_lastUpdated,并使用此方法构建要在存储库的作业检索方法中返回的作业时。
答案 0 :(得分:2)
在我看来,你有各种各样的选择。
选项1
假设您的存储库有两种方法:
public IEnumerable<Job> ReadAll() { ... }
public int CreateJob(Job job) { ... }
您可以为Job
类提供两个构造函数,一个采用DateTime
而另一个采用public class Job
{
public Job(DateTime startDate)
{
this.StartDate = startDate;
}
public Job() : this(DateTime.UtcNow)
{
}
public DateTime StartDate { get; private set; }
}
。
startDate
这并不妨碍服务调用&#34;错误&#34;构造函数,但至少它传达了调用它而没有Job
给调用者的选项。
选项2
使用两个不同的public IEnumerable<Job> ReadAll() { ... }
public int CreateJob(NewJob newJob) { ... }
类。
您的存储库可能会这样:
NewJob
public class NewJob
{
public NewJob()
{
this.StartDate = DateTime.UtcNow;
}
public DateTime StartDate { get; private set; }
}
类看起来像:
Create
这更好地传达了意图,因为存储库的NewJob
方法只接受NewJob
的实例,因此模型的用户将被强制创建Job
而不是StartDate
。
选项3
忽略repostory的Create
方法中的DateTime.UtcNow
,并始终在方法中将其设置为Insert
。甚至可以在设置它的数据库中创建一个{{1}}触发器。
答案 1 :(得分:1)
一种常见的方法是使用构造函数来实现这个
public class Job
{
private DateTime _startDate;
public void Job()
{
_startDate = DateTime.UtcNow;
}
public void Job(DateTime dt)
{
// check DateTime kind, this could be source of a bug
if(dt.Kind != DateTimeKind.Utc) throw new ...
_startDate = dt;
}
}
您必须以某种方式公开此方法/属性。如果存储库可以设置它,您可以从其他位置设置它。如果你试图聪明一点(你可以,例如通过使用接口),你就会面临过度工程的风险。
答案 2 :(得分:1)
您正在进行DDD的主要原因之一是利用封装提供的托管可变性。 总是将从构造函数开始。
通常,这是ORM专门设计用于执行的工作类型,但是它也可以利用已使用memento pattern映射到域对象的任何现有DTO:
public Job() {
_lastUpdated = DateTime.UtcNow;
// ...
}
public Job(JobData data) {
_lastUpdated = data.LastUpdated;
//...
}
重新:AutoMapper
- 自从我使用它以来已经过了一段时间了,但它应该是 possible for you to instruct it to access fields using reflection in the configuration。