簡體   English   中英

通用靜態類 - 在運行時檢索對象類型

[英]Generic static class - retrieving object type in run-time

我有一個X類型的對象,我可以(顯然)在運行時檢索。

var type = myObject.GetType();

我有一個通用的靜態類。

public static class MyStaticClass<T>
{
    public static void DoStuff(T something)
    {
        // bla bla
    }
}

我想做的是:

MyStaticClass<myObject.GetType()>.DoStuff(myObject);

但我不能。

實際上,MyStaticClass只有幾種類型可以運行,它們共享多個接口。 一個解決方法是寫:

if (myObject.GetType() == typeof(X))
{
    MyStaticClass<X>.DoStuff(myObject as X);
}
if (myObject.GetType() == typeof(Y))
{
    MyStaticClass<Y>.DoStuff(myObject as Y);
}

但它的冗長和寫作處處實在是太丑了-我覺得我不應該這樣做,而且我不應該這樣做。

我無法相信沒有解決方案。 或者至少有任何整潔的解決方法? 或者我的方法開始時是錯誤的(如果是這樣的替代方案)? 我應該為X,Y,Z創建一些(抽象?)基類嗎?

您可以使用Type.MakeGenericType通過反射執行此Type.MakeGenericType - 但是您需要使用反射來調用該方法。 雖然這有點痛苦。

如果你使用的是C#4,你可以使用動態類型和類型推斷 - 雖然這只適用於泛型方法而不是泛型類型 ,所以你需要使用:

public void DoStuffDynamic(dynamic item)
{
    DoStuffHelper(item);
}

private static void DoStuffHelper<T>(T item)
{
    MyClass<T>.DoStuff(item);
}

編輯:為了表現,你可以避免做太多的實際反思。 您可以對每個項類型執行一次反射,創建Action<object>形式的委托,並將其緩存在字典中。 這比在每次執行時執行反射快得多。

這是一個簡短但完整的樣本:

using System;
using System.Collections.Generic;
using System.Reflection;

public static class MyStaticClass
{
    private static readonly object mapLock = new object();

    private static readonly Dictionary<Type, Action<object>>
        typeActionMap = new Dictionary<Type, Action<object>>();

    private static readonly MethodInfo helperMethod =
        typeof(MyStaticClass).GetMethod("ActionHelper",
                                        BindingFlags.Static |
                                        BindingFlags.NonPublic);

    public static void DoStuffDynamic(object item)
    {
        if (item == null)
        {
            throw new ArgumentNullException("item");
        }

        Type type = item.GetType();
        Action<object> action;
        lock (mapLock)
        {
            if (!typeActionMap.TryGetValue(type, out action))
            {
                action = BuildAction(type);
                typeActionMap[type] = action;
            }
        }
        action(item);
    }

    private static Action<object> BuildAction(Type type)
    {
        MethodInfo generic = helperMethod.MakeGenericMethod(type);
        Delegate d = Delegate.CreateDelegate(typeof(Action<object>),
                                             generic);
        return (Action<object>) d;
    }

    private static void ActionHelper<T>(object item)
    {
        MyStaticClass<T>.DoStuff((T) item);
    }
}


public static class MyStaticClass<T>
{
    public static void DoStuff(T something)
    {
        Console.WriteLine("DoStuff in MyStaticClass<{0}>",
                          typeof(T));
    }
}

public class Test
{
    static void Main()
    {
        MyStaticClass.DoStuffDynamic("Hello");
        MyStaticClass.DoStuffDynamic(10);        
    }
}

當我我只能用這樣的事情,但偶爾也有真的沒有任何明智的選擇。

“實際上,MyStaticClass只有幾種類型可以運行,並且它們共享多個接口。一種解決方法是編寫:”

那么你能不能針對共享interface編寫DoStuff方法嗎? 這樣您就可以針對已知接口進行編程,而不是試圖猜測對象的類型。 整個方法似乎有點狡猾。 然后你可以完全刪除泛型。

如果沒有反射,這是不可能的,必須在編譯時知道泛型類型參數。 即使有可能通過反思,我也會反對。 你應該改變你的設計。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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