2014-01-08 30 views
2

我有一個抽象基類的一些推廣方法的類型參數,讓我們說Pet,這本身調用了該類型參數的通用方法。獲得一個通用的方法來推斷從運行時類型

public static Pet_ExtensionMethods 
{ 
    public static T PermuteFromData<T>(this T thisPet, string data) where T : Pet 
    { 
     T newPet = new SomeDeserializer().Deserialize<T>(data); 
     newPet.someProperty = thisPet.someProperty; 
     return newPet; 
    } 
} 

這爲我偉大的工作,我可以說這樣的話:

Dog newDog = existingDog.PermuteFromData(dogData); 
Cat newCat = existingCat.PermuteFromData(catData); 

而且都具有相同的基本實現無代碼重複。

但我最近發現了一個令人不安的問題!如果我去:

Pet myPet = existingDog; 
string petData = dogData; 
Pet newPet = myPet.PermuteFromData(petData); 

我想要的行爲是相同的,但現在的編譯器選舉運行PermuteFromData<Pet>進而調用Deserialize<Pet>,這在一些圖書館的深處,我不控制嘗試去Activator.CreateInstance(typeof(T)) - 爲嘗試創建Abstract類的實例拋出異常!

我發現的唯一解決方法是嘔出來下面的代碼使用運行時類型,以獲得正確的泛型方法:

public static T PermuteFromDataFix<T>(this T thisPet, string data) where T : Pet 
{ 
    return (T) typeof(Pet_ExtensionMethods).GetMethod("PermuteFromData") 
     .MakeGenericMethod(new Type[] { thisPet.GetType() }) 
     .Invoke(null, new object[] { thisPet, data }); 
} 

爲了上帝的愛,還有沒有其他的辦法嗎?硬編碼的字符串與類中的方法名稱是不可接受的。

我有這樣一大堆的擴展方法,其中通用的方法需要推斷運行時類型,而不是編譯時類型。 Someone告訴我,我可以巧妙地使用dynamic來解決這個問題。是這樣嗎?

回答

1

您可以嘗試使用dynamic,但我不知道你能做到這一點使用擴展方法的語法。

試試這一個第一:

Pet_ExtensionMethods.PermuteFromData((dynamic)pet, petData); 

應該按預期工作。然後你可以嘗試

((dynamic)pet).PermuteFromData(petData); 

但我不確定它會解決糾正方法。

+0

你找到了我:) – Alain

相關問題