2014-01-08 44 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