2009-12-19 113 views
2

我有一個倉儲類兩個通用的保存方法:如何編寫處理單個對象和集合的通用Save()方法?

public void Save<T>(T entity) 
{ 
    _session.Save(entity); 
} 

public void Save<T>(IEnumerable<T> entities) 
{ 
    foreach (var item in entities) 
    { 
     _session.Save(item); 
    } 
} 

然而,當我使用Save(collection)(自動推斷類型),它認識到它作爲一個T而非IEnumerable<T>並嘗試使用,以保存第一種方法。

我該如何編寫這個保存方法以便它可以處理這兩種情況,而無需我明確提供類型?

回答

4

將類型參數放在存儲庫上的類級別上,而不是在方法級別上,這樣重載就不會含糊不清了。

class Repo<T> 
{ 
    public void Save(T entity) 
    { 
     _session.Save(entity); 
    } 

    public void Save(IEnumerable<T> entities) 
    { 
     foreach (var item in entities) 
     { 
      _session.Save(item); 
     } 
    } 
} 

你會使用這樣的:

var repo = new Repo<Person>(); 

var p = new Person(); 
repo.Save(p); 

var ps = new Person[] { p }; 
repo.Save(ps); 
+0

如果我想保持無類型的存儲庫,該怎麼辦?我希望能夠通過將類型傳遞給'Get()'來實例化存儲庫並查詢任何實體。這爲我省去了實例化同一個存儲庫的多個副本的麻煩,其中它們之間的唯一區別是類型。 – 2009-12-19 08:48:31

+0

爲了澄清,我希望能夠這樣做:'var repo = new Repository(); repo.Get (); repo.Get (); repo.Get ();'代替:var repo1 = new Repository (); var repo2 = new Repository (); var repo3 = new Repository ();'。 – 2009-12-19 08:50:51

0

Whjy不屑於重載方法?是不是好做它喜歡:

public void Save<T>(T entity) 
{ 
    if (T is IEnumerable) 
    { 
     foreach (var item in entity) 
       _session..Save(item); 
    } else { 
     _session.Save(entity); 
    } 
} 
+0

這並不遵循SRP。參數的名稱沒有準確地描述它可能包含的值的事實是一個大的代碼味道警告。 – 2009-12-19 03:17:03

+0

似乎優雅地工作的一種解決方案是將其分成兩個具有不同簽名的獨立方法。 – 2009-12-19 03:32:43

1

你不能依靠類型推斷這個特定的情況下。 <T>(T)將滿足任何類型,因此推斷不會繼續搜索以找到更符合簽名的更具體的約束條件。

0

你可以這樣使用它也:

public void Save<T>(T entity) 
    { 
     if (typeof(T).GetInterfaces().Contains(typeof(IEnumerable))) 
     { 
      SaveEnumerable(entity as IEnumerable); 
     } 
     else 
     { 
      _session.Save(entity); 
     } 
    } 

    public void SaveEnumerable(IEnumerable entities) 
    { 
     foreach (var item in entities) 
     { 
      _session.Save(item); 
     } 
    } 

希望這有助於!

相關問題