我写我自己一个漂亮简单的小域模型,与对象图,看起来像这样从构建扁平DTO的对象图:使用访问者模式
-- Customer
-- Name : Name
-- Account : CustomerAccount
-- HomeAddress : PostalAddress
-- InvoiceAddress : PostalAddress
-- HomePhoneNumber : TelephoneNumber
-- WorkPhoneNumber : TelephoneNumber
-- MobilePhoneNumber : TelephoneNumber
-- EmailAddress : EmailAddress
这种结构是完全在赔率我必须使用遗留数据库,所以我定义了一个扁平的DTO,它包含客户图中每个元素的数据 - 我在数据库中具有视图和存储过程,这些视图和存储过程允许我使用数据进行交互这两个方向的扁平结构,这一切工作正常&丹迪:)
将领域模型扁平化为DTO以进行插入/更新很简单,但是我遇到的问题是采用DTO并从中创建领域模型......我的第一个想法是实现访问每个元素的访问者在客户图形,并在必要时注入从DTO值,东西有点像这样:
class CustomerVisitor
{
public CustomerVisitor(CustomerDTO data) {...}
private CustomerDTO Data;
public void VisitCustomer(Customer customer)
{
customer.SomeValue = this.Data.SomeValue;
}
public void VisitName(Name name)
{
name.Title = this.Data.NameTitle;
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
}
// ... and so on for HomeAddress, EmailAddress etc...
}
这是理论和它看起来像时,它的布局只是这样的:)
完善思路但为了这个工作,整个对象图需要在访问者erm访问之前构建,否则我会得到NRE的左侧和中间。
我想要做的就是让访问者在访问每个元素时将对象分配给图形,目标是对DTO中缺少数据的对象使用特殊情况模式,例如。
public void VisitMobilePhoneNumber(out TelephoneNumber mobileNumber)
{
if (this.Data.MobileNumberValue != null)
{
mobileNumber = new TelephoneNumber
{
Value = this.Data.MobileNumberValue,
// ...
};
}
else
{
// Assign the missing number special case...
mobileNumber = SpecialCases.MissingTelephoneNumber.Instance;
}
}
这一点我真的以为会工作,但C#引发我一个错误的:
myVisitor.VisitHomePhone(out customer.HomePhoneNumber);
因为你不能用这种方式:(
所以通过REF/out参数我留下来访问独立元素,并在完成时重建图形:
在此po诠释我知道我离访客模式很远,而且离工厂更近,我开始怀疑我是否从一开始就错误地接近了这个事情..
有其他人跑过成这样的问题?你是如何克服它的?有没有适合这种情况的设计模式?
对不起张贴这样的looong问题,并阅读这远:)
编辑在回答弗洛里安格莱纳赫和gjvdkamp的有用的答案做得很好,我最后选择了一个相对简单的工厂实现看起来像这样:
class CustomerFactory
{
private CustomerDTO Data { get; set; }
public CustomerFactory(CustomerDTO data) { ... }
public Customer CreateCustomer()
{
var customer = new Customer();
customer.BeginInit();
customer.SomeFoo = this.Data.SomeFoo;
customer.SomeBar = this.Data.SomeBar
// other properties...
customer.Name = this.CreateName();
customer.Account = this.CreateAccount();
// other components...
customer.EndInit();
return customer;
}
private Name CreateName()
{
var name = new Name();
name.BeginInit();
name.FirstName = this.Data.NameFirstName;
name.LastName = this.Data.NameLastName;
// ...
name.EndInit();
return name;
}
// Methods for all other components...
}
然后我写了一个ModelMediator类来处理数据层和领域模型之间的互动...
class ModelMediator
{
public Customer SelectCustomer(Int32 key)
{
// Use a table gateway to get a customer DTO..
// Use the CustomerFactory to construct the domain model...
}
public void SaveCustomer(Customer c)
{
// Use a customer visitor to scan for changes in the domain model...
// Use a table gateway to persist the data...
}
}
像Automapper这样的东西会为你工作吗? HTTP://automapper.codeplex。com/ – bentayloruk 2011-06-02 16:52:42
@bentayloruk谢谢你的回应,我已经评估过automapper(和valueinjeter),但不幸的是,这两者都不合适,因为我的域对象实现了ISupportInitialize,而且在注入DTO中的任何属性之前需要BeginInit(),EndInit ()后 - 我不认为这是可能的与Automapper :( – MattDavey 2011-06-02 20:47:02
如果您使用.net 4,那么我会建议懒惰类将帮助你一点:) –
Nathan
2011-06-06 08:31:19