【发布时间】:2012-04-19 22:07:33
【问题描述】:
这是一个如此简单和常见的场景,我想知道我是怎么做到的,为什么我现在遇到问题。
我有这个对象(基础设施程序集的一部分)
public class Queue {}
public class QueueItem
{
public QueueItem(int blogId,string name,Type command,object data)
{
if (name == null) throw new ArgumentNullException("name");
if (command == null) throw new ArgumentNullException("command");
BlogId = blogId;
CommandType = command;
ParamValue = data;
CommandName = name;
AddedOn = DateTime.UtcNow;
}
public Guid Id { get; internal set; }
public int BlogId { get; private set; }
public string CommandName { get; set; }
public Type CommandType { get; private set; }
public object ParamValue { get; private set; }
public DateTime AddedOn { get; private set; }
public DateTime? ExecutedOn { get; private set; }
public void ExecuteIn(ILifetimeScope ioc)
{
throw new NotImplementedException();
}
}
这将在另一个这样的程序集中创建
var qi = new QueueItem(1,"myname",typeof(MyCommand),null);
这里没有什么不寻常的。但是,该对象将被发送到将被持久化的存储库。Queue 对象将向存储库询问项目。存储库应重新创建 QueueItem 对象。
但是,如您所见,QueueItem 属性是不变的,AddedOn 属性应该只在创建项目时设置一次。 Id 属性将由 Queue 对象设置(这并不重要)。
问题是我应该如何在存储库中重新创建 QueueItem?我可以有另一个构造函数,它需要所有属性的每个值,但我不希望该构造函数可用于最初将创建队列项的程序集。存储库是不同程序集的一部分,因此内部无法工作。
我想过提供一个工厂方法 类队列项 { /* ..其余定义.. */
public static QueueItem Restore(/* list of params*/){}
}
这至少清除了意图,但我不知道为什么我不喜欢这种方法。我也可以仅通过 Queue 强制创建项目,但这意味着将 Queue 作为依赖项传递给 repo,这又不是我想要的。为此拥有一个特定的工厂对象,似乎也有点矫枉过正。
基本上我的问题是:在存储库中重新创建对象的最佳方式是什么,不将特定的创建功能公开给另一个消费者对象。
更新
重要的是要注意,存储库是指模式本身作为抽象,而不是 ORM 的包装器。域对象的持久化方式或位置无关紧要。重要的是如何由存储库重新创建。另一个重要的事情是我的域模型 与持久性模型不同。我确实使用了 RDBMS,但我认为这只是一个不应该具有任何重要性的实现细节,因为我正在寻找不依赖于特定存储访问的方法。
虽然这是一个特定场景,但它基本上可以应用于将由 repo 恢复的每个对象。
更新2
好吧,我不知道我怎么会忘记 AutoMapper。我的错误印象是它不能映射私有字段/setter,但它可以,我认为这是最好的解决方案。
事实上,我可以说最佳解决方案 (IMO) 是有序的:
- 如果可用,直接反序列化。
- 自动映射。
- 域对象本身的工厂方法。
前两个不要求对象特别做任何事情,而第三个要求对象为这种情况提供功能(一种输入有效状态数据的方法)。它有明确的意图,但它几乎可以完成映射工作。
回答 更新
回答我自己,在这种情况下,最佳方法是使用工厂方法。最初我选择了 Automapper,但我发现自己更频繁地使用工厂方法。 Automapper 有时很有用,但在很多情况下还不够。
【问题讨论】:
-
有点离题,但如果这是您“域”的一部分,您可能需要考虑使用 NServiceBus 或 MassTransit 之类的工具。
标签: oop domain-driven-design factory-pattern