2009-09-01 69 views
4

我有以下代碼的情況,我懷疑可能有點dodgey:訪問靜態方法在泛型類在C#

我有一個類:

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 

該類DataAccessBase也有這其中一個語句創建使用枚舉值本身派生類的實例的靜態工廠方法來決定哪些派生類型創建:

static IDataAccess CreateInstance(TypeToCreateEnum) 

現在,TY從DataAccessBase<T>衍生PES本身不是通用的,他們指定類型爲T:

class PoLcZoneData : DataAccessBase<PoLcZone> // PoLcZone is derived from AnotherAbstractClass 

到目前爲止,我不知道這是否是推好使用泛型的限制,但我真的很關心的是如何首先訪問靜態CreateInstance()方法:

我現在這樣做的方式是簡單地通過任何類型T,其中T:AnotherAbstractClass。特別是我本身通過AnotherAbstractClass。這樣可以很好地進行編譯,但是在我看來,將任何類型傳遞給泛型類只是爲了獲得靜態的數據有點不方便。

其實我已經簡化了局面有所爲DataAccessBase<T>是繼承鏈中的較低水平,但靜態工廠方法都存在一箇中間層與如PoLcZoneData爲最衍生的不是通用唯一的一級類。

這種安排是什麼人民的想法?

+0

這是什麼語言? – 2009-09-01 03:18:50

+0

對不起,它的C#。忘了添加到標題。 – MrLane 2009-09-01 03:19:46

回答

9

你被允許有一個非通用類的同名......也許是這樣的:

abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass 
{ 
    ... 
} 
static class DataAccessBase 
{ 
    public static IDataAccess CreateInstance(TypeToCreateEnum) {...} 
} 

現在你可以使用DataAccessBase.CreateInstance沒有任何多餘的T。通常情況下,您可以撥打internal方法DataAccessBase<T>DataAccessBase - 雖然我懷疑在您的情況下,您可能還需要一點反思/ MakeGenericType

0

我不認爲這種設計有什麼問題,特別是如果您使用模板參數來指定實現細節。我所建議的只是讓工廠的功能不是靜態的,而只是一個獨立的。這對我來說是最清晰的方式。

如果你想以某種方式封裝它,我會建議一個命名空間或命名約定。

又一解決方案將只是躲在目前你在做什麼,通過定義也許像這樣一類DataAccessBase的:

typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory; 

這是我最推薦的解決方案,但它留下的創建函數爲靜態如果你絕對想要它。

+0

@killerfox這是c# – 2009-09-01 03:24:43

+0

好吧,在這種情況下,我想唯一的選擇是將工廠函數封裝在一個單獨的類而不是名稱空間 – 2009-09-01 03:36:01

2

我前段時間遇到類似的問題(「如何重載靜態方法」),我用Reflection解決了它。

這裏是我的情況:

1)public abstract class AuditObject<T> : ActiveRecordBase<T>(是的,我使用ActiveRecord)和

2)public class Employee : AuditObject<Employee>

在他們兩個我定義了一些靜態方法,例如

public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    return doExtremelyCleverStuffToFetchData(where, topRows); 
} 

(在#2你需要public **new** static否則你會得到一個編譯器警告)

由於代碼是,當我打電話例如

DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 

...,T是僱員,靜態方法不是「被覆蓋的」,即所執行的一個是在方法(1),而不是(2)。

所以在(1)我修改了靜態方法(在這個例子中,GetLookupTable)是這樣的:

public static DataTable GetLookupTable(String where, Int32 topRows) 
{ 
    DataTable tbl = null; 

    Boolean hasOverride = hasMethodOverride("GetLookupTable"); 

    if (hasOverride) 
    { 
     tbl = invokeStaticMethod<T>(
      "GetLookupTable", new Object[2] { where, topRows }) 
      as DataTable; 
    } 
    else 
    { 
     tbl = doExtremelyCleverStuffToFetchData(where, topRows); 
    } 

    return tbl; 
} 

以下是我發現如果靜態方法存在:

private static Boolean hasMethodOverride(String methodName) 
{ 
    var methodQuery = 
     from method in typeof(T).GetMethods(
      BindingFlags.Static | BindingFlags.Public | BindingFlags.InvokeMethod) 
     where method.Name == methodName 
     select method; 

    return methodQuery.Count() > 0; 
} 

而且這裏是如何調用「覆蓋」方法:

public static Object invokeStaticMethod<T>(String MethodName, Object[] Args) 
{ 
    return typeof(T).InvokeMember(MethodName, 
     BindingFlags.Public | BindingFlags.Static | BindingFlags.InvokeMethod, 
     null, null, Args); 
} 

瞧!當我致電DataTable myList = AuditObject<T>.GetLookupTable("inactive = 0", 100); 並且T是Employee時,我從Employee類中定義的靜態方法獲得結果。

希望這有助於

季米特里斯