簡體   English   中英

在c#中訪問泛型類的靜態方法

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM