我寫我自己一個漂亮簡單的小域模型,與對象圖,看起來像這樣從構建扁平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