[英]Accessing Static Methods on a Generic class in c#
我在代碼中有以下情況,我懷疑這可能有點過於謹慎:
我有一節課:
abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass
此類DataAccessBase
還有一個靜態工廠方法,該方法使用where語句中的枚舉值創建自身派生類的實例,以決定要創建的派生類型:
static IDataAccess CreateInstance(TypeToCreateEnum)
現在,從DataAccessBase<T>
派生的類型本身不是通用的,它們為T指定了一個類型:
class PoLcZoneData : DataAccessBase<PoLcZone> // PoLcZone is derived from AnotherAbstractClass
到目前為止,我不確定這是否正在推動使用泛型的極限,但我真正關心的是如何首先訪問靜態CreateInstance()
方法:
我現在這樣做的方法是簡單地傳遞任何類型T T: AnotherAbstractClass
。 特別是我正在傳遞AnotherAbstractClass
本身。 這允許編譯很好,但在我看來,將任何類型傳遞給泛型類只是為了得到靜態有點過於愚蠢。
我實際上已經簡化了這種情況,因為DataAccessBase<T>
是繼承鏈中的較低級別,但靜態工廠方法存在於中間層,其中諸如PoLcZoneData
類的類是在非泛型的唯一級別上派生得最多的。
人們對這種安排的看法是什么?
你可以擁有一個同名的非泛型類......也許是這樣的:
abstract class DataAccessBase<T> : IDataAccess where T : AnotherAbstractClass
{
...
}
static class DataAccessBase
{
public static IDataAccess CreateInstance(TypeToCreateEnum) {...}
}
現在您可以使用DataAccessBase.CreateInstance
而無需任何冗余T
通常,您可以從DataAccessBase
調用DataAccessBase<T>
上的internal
方法 - 盡管我懷疑在您的場景中您可能還需要一點反射/ MakeGenericType
。
我剛才遇到了類似的問題(“如何重載靜態方法”),我用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是Employee,靜態方法不是“覆蓋”,即執行的是(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類中定義的靜態方法得到結果。
希望這可以幫助,
季米特里斯
我不認為該設計有任何問題,特別是如果您使用模板參數指定實現細節。 我建議的只是讓工廠的功能不是靜止的,而只是一個獨立的。 這對我來說是最明確的方式。
如果你想以某種方式封裝它,我會建議命名空間或命名約定。
另一個解決方案是隱藏你當前正在做的事情,通過定義一種類型的DataAccessBase可能是這樣的:
typedef DataAccessBase<AnotherAbstractClass> DataAccessBaseFactory;
這是我最不推薦的解決方案,但如果你絕對想要它,它會將Create函數保留為靜態。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.