2011-12-13 64 views
4

我正在玩域驅動開發。我使用的定義如下通用倉庫實現:(這是實現爲Repository<T>帶有存儲庫的域驅動設計中的對象創建策略

public interface IRepository<T> where T : class, IEventSource, new() 
    { 
     T FindByKey(Guid key); 
     IEnumerable<T> FindByQuery(Predicate<T> filter); 
     IEnumerable<T> GetAll(); 
     T CreateObject(); 
    } 

比方說,我有一個Order類,即不能沒有客戶參數做成。我使用CreateObject來設置實體的Key和一個連續的Guid生成器。

什麼是最小化開發時間和耦合的解決方案?

  • 目前,我有一個參數的構造函數,和我打電話一些 初始化(客戶)方法。
  • 我可以創建一個ICustomerRepository,但這意味着每個實體都會有大量的額外開發時間。
  • 我也可以修改CreateObject以獲取params object[] args,但在編譯時這不是安全的。
  • 我可以刪除CreateObject並使用構造函數來創建對象,但這意味着我需要訪問Guid生成算法,無論哪裏我實例化一個對象,增加耦合。
  • 在實體的基類中,我可以在構造函數中設置鍵,減少耦合,但需要對算法進行一些靜態引用。

更新

我實現以下SLL的答案戰略。對於庫中的新簽名現在是:

public interface IRepository<T> where T : class, IEventSource 
{ 
    T FindByKey(Guid key); 
    IEnumerable<T> FindByQuery(Func<T, bool> predicate); 
    IEnumerable<T> GetAll(); 
    T CreateObject(); 
    T CreateObject(IConstructorParameters parameters); 
} 

無參數CreateObject試圖通過調用參數的構造函數(使用IL:發射性能)創建一個實例。

第二CreateObject嘗試創建調用構造,其中上IConstructorParameters屬性實體對象上的構造相匹配的方法。

實現:

private Dictionary<Type, Func<IConstructorParameters, T>> _constructionMethods 
    = new Dictionary<Type, Func<IConstructorParameters, T>>(); 
public T CreateObject(IConstructorParameters args) 
{ 
    T newObject; 
    if (args == null) 
    { 
     args = ConstructorParameters.Empty; 
    } 
     Type paramType = args.GetType(); 
     Func<IConstructorParameters, T> constructor; 

     if (!_constructionMethods.TryGetValue(paramType, out constructor)) 
     { 
      //Emit IL to create a Func<IConstructorParameters,T> 
      constructor = CreateConstructor(paramType); 
      _constructionMethods.Add(paramType, constructor); 
     } 

     newObject = constructor(args); 

    newObject.Key = _guidCreator.Generate(); 
    return newObject; 
} 
+0

是否有將CreateObject()方法放入存儲庫的特殊原因,即使用通用方法創建對象有什麼好處?在DDD中,我認爲創建對象將是工廠而不是倉庫的責任。通常情況下,存儲庫將具有用於將現有對象添加到商店的Add方法。 – David

+0

這是一個很好的觀點,如果我將其添加到工廠並希望保持其通用性,則同樣的情況適用。 – Bas

+0

@BasB你應該考慮停止使所有東西都是通用的,如果你需要一些參數,你不能使你的對象創建爲通用的,不要太嚴格地應用DRY。 –

回答

1

如果您不希望實現IOrderRepository - 你可以像IConstructionParameters接口抽象CreateObject()方法參數,然後爲每個實體實現諸如OrderConstructionParameters具體參數。

這種方法也被稱爲Parameter Object設計模式其中設計理由 - 更多decoupled系統設計。

public interface IRepository<T> 
{ 
    T CreateObject(IConstructionParameters parameters);  
} 

public sealed class OrderConstructionParameters : IConstructionParameters 
{ 
    public Customer Customer 
    { 
     get; 
     private set; 
    } 
} 
+0

聽起來像一個計劃,將檢查是否可以創建一個IL發射器,基於此創建對象。 – Bas

2

的幾點建議作爲,我會做如下。

  • 保持IRepository通用的,也只有什麼是相關的實體,ICustomerRepository作爲例子創建一個包含合同特定的接口。
  • 將guid生成移除到服務類,因爲此任務與基礎結構最爲相關,而不是域。
+0

我在接口IGuidGeneration中使用依賴注入來解析GUID。 – Bas

+0

沒關係,但是混合基礎設施和域,可能不是那麼理想,即使是依賴注入。 – wnascimento

相關問題