2012-04-20 79 views
2

我正在研究一個應用程序,我需要根據調用類的泛型類型調用兩種數據方法之一。例如,如果T是Foo類型的,我會打電話給data.GetFoo():基於類型調用DAL方法

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     return data.GetFoo(mostRecentProcessedReadTime); // Notice GetFoo() 
    } 
} 

如果T是類型吧,我會打電話給data.GetBar():

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     return data.GetBar(mostRecentProcessedReadTime); // Notice GetBar() 
    } 
} 

在此之前,我只需要一個DAL方法,因爲所有類型都以相同的方式檢索。我現在需要調用兩種方法之一,這取決於我試圖避免類似事情的類型T.

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (MesReportingDal data = new MesReportingDal()) 
    { 
     if (T is Foo) { return data.GetFoo(mostRecentProcessedReadTime); } 
     if (T is Bar) { return data.GetBar(mostRecentProcessedReadTime); } 
    } 
} 

這違反了OCP。有沒有一個優雅的方式來處理這個問題,所以我可以擺脫我的if語句?

編輯 - 這是種什麼樣子

public partial class Foo1 : IDataEntity { } 
public partial class Foo2 : IDataEntity { } 
public partial class Bar1 : IDataEntity { } 
public partial class Bar2 : IDataEntity { } 

這些FOOS和酒吧都與LINQ到SQL使用的DBML項目。

+0

你有一個'T'類的控制 - 他們可以改變,你有基礎接口/類等 – NSGaga 2012-04-20 13:54:48

+0

請參閱我的編輯。這有幫助嗎? – 2012-04-20 13:57:26

+0

如果你不想改變Foo *,Bar *並且它必須是GetFoo,GetBar - 不是Get()asaddeini建議的(如果我明白了嗎?)。你打算如何「調用」GetObjectList()?你在定義例如Foo,Bar在通話之前(所以你有例如一個類型化的變量) - 或者你想以某種高度通用的方式調用它(使用另一種通用方法的T)?如果可以的話,最簡單的就是ataddeini所說的。 – NSGaga 2012-04-20 14:19:25

回答

3

我會更改GetFooGetBar只是Get,並使MesReportingDal也是通用的。

所以我認爲你最終會得到這樣的:

private static List<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (var data = new MesReportingDal<T>()) 
    { 
     return data.Get(mostRecentProcessedReadTime);   
    } 
} 

順便說一句,具有using聲明還要求MesReportingDal實現IDisposable,否則你會得到下面的編譯錯誤:

「MesReportingDal」:在使用語句中使用的類型必須是隱式轉換爲「System.IDisposable的」

UPDATE

因此,在考慮了這一點之後,閱讀您的反饋意見,您有一個選項是提取存儲庫接口並將創建重新推回到工廠方法。這將讓你保持單data.Get(...)電話,但基於T

public interface IRepository<T> : IDisposable 
{ 
    IList<T> Get(DateTime mostRecentRead); 
} 

public class FooRepo : IRepository<Foo> 
{ 
    public IList<Foo> Get(DateTime mostRecentRead) 
    { 
     // Foo Implementation 
    } 
} 

public class BarRepo : IRepository<Bar> 
{ 
    public IList<Bar> Get(DateTime mostRecentRead) 
    { 
     // Bar Implemenation 
    } 
} 

你的工廠則可能是這個樣子

public class RepositoryFactory 
{ 
    public static IRepository<T> CreateRepository<T>() 
    { 
     IRepository<T> repo = null; 
     Type forType = typeof(T); 

     if (forType == typeof(Foo)) 
     { 
      repo = new FooRepo() as IRepository<T>; 
     } 
     else if (forType == typeof(Bar)) 
     { 
      repo = new BarRepo() as IRepository<T>; 
     } 

     return repo; 
    } 
} 

,這將讓你保持你的初始代碼不同的實現塊清潔

private static IList<T> GetObjectList(DateTime mostRecentProcessedReadTime) 
{ 
    using (var data = RepositoryFactory.CreateRepository<T>()) 
    { 
     return data.Get(mostRecentProcessedReadTime); 
    } 
} 

希望有所幫助。

+0

我不知道這會起作用,這可能是因爲我不是很清楚。 data.Get()方法根據類型具有不同的實現。 Get()中的算法不同。 – 2012-04-20 15:52:46

+0

@BobHorn對,好。考慮到這一點,我不斷回到倉庫界面和工廠。我會盡量用一個例子來更新。 – ataddeini 2012-04-21 12:21:09

+0

謝謝。雖然這推動了其他地方的if邏輯,但它確實保持了消費代碼的清潔。我一直希望完全避免* if *邏輯,但是這種解決方案至少可以將它保留在工廠內。我認爲我唯一的選擇是反思,但現在可以運作。 – 2012-04-21 17:51:16