2017-05-10 270 views
0

泛型类的实例,我需要这样的创建一个通用类的实例:创建动态泛型类型参数

Type T = Type.GetType(className).GetMethod(functionName).ReturnType; 
var comparer = new MyComparer<T>(); // ERROR: "The type or namespace name 'T' could not be found" 

我发现这个answer哪里,这是可能仅与反思。但使用反射我得到的对象,我需要投给我的泛型类型。我试过像这样

Type myGeneric = typeof(MyComparer<>); 
Type constructedClass = myGeneric.MakeGenericType(); 
object created = Activator.CreateInstance(constructedClass); 
var comparer = (T)Convert.ChangeType(created, T);// ERROR: "The type or namespace name 'T' could not be found" 

但是得到相同的错误。如何解决它?

下面是一个完整的例子:

public static bool Test(string className, string functionName, object[] parameters, object correctResult) 
    { 
     var method = Type.GetType(className).GetMethod(functionName); 
     Type T = method.ReturnType; 
     var myResult = method.Invoke(null, parameters); 
     dynamic myResultAsT = Convert.ChangeType(myResult, T); 
     dynamic correctResultAsT = Convert.ChangeType(correctResult, T); 
     var comparer = new MyComparer<T>(); // Problem is here!!!  
     return comparer.Equals(myResultAsT, correctResultAsT);    
    } 

的想法是做一个单元测试,它将调用带有参数的功能,并将其结果与正确结果进行比较。但我需要自定义比较器,所以我实现MyComparer,由于编译器错误,我无法使用它。

public class MyComparer<T> : IEqualityComparer<T> 
{ 
    public bool Equals(T x, T y){/* some implementation*/} 
} 
+0

你的错误信息没有意义,你确定这是他们说的吗? – DavidG

+0

@DavidG完整的编译器错误是:'无法找到类型或名称空间名称'T'(缺少using指令还是程序集引用?)'。为什么它没有意义? – Dejan

+1

然后你没有显示足够的代码,请显示[mcve] – DavidG

回答

0

我觉得很简单的解决问题。有没有必要投object到特定类型的T,只是使用dynamic关键字,而不是铸造

Type myGeneric = typeof(MyComparer<>); 
    Type constructedClass = myGeneric.MakeGenericType(T); 
    object created = Activator.CreateInstance(constructedClass); 
    dynamic comparer = created; // No need to cast created object to T 

,然后我可以用比较器通常调用它的方法,如:

return comparer.Equals(myResultAsT, correctResultAsT); 

LueTm评论,可能再次使用反射并调用比较器方法,但这种解决方案看起来更容易。

+0

这是更好的解决方案。 – LueTm

0

看起来你几乎没有:

// t is a variable, so make it lowercase. This is where some of the confusion comes from 
Type t = Type.GetType(className).GetMethod(functionName).ReturnType; 
Type myGeneric = typeof(IEqualityComparer<>); 

// You need to provide the generic type to make it generic with 
// You want IEqualityComparer<T>, so: 
Type constructedClass = myGeneric.MakeGenericType(t); 

// Now create the object 
object created = Activator.CreateInstance(constructedClass); 

// This is tricky without more context... 
// You could try this, but to tell you more I would need to know where you use 
// the comparer instance. Are you using it in a LINQ query, or in a Sort()? 
// If so just cast it to a IEqualityComparer<YourType>, and 
// make YourType whaterver you need it to be in the list or the query... 
var comparer = (IEqualityComparer<object>)created; 
+0

现在,它正在编译,但它在运行时抛出InvalidCastException。 '无法投射类型为'MyComparer1 [System.Double]'的对象以键入'MyComparer1 [System.Object]'。“我使用的是Myconnor,内含IEqualityComparer。 – Dejan

+0

我使用比较器实例仅用于具有两个对象的'Equals'。我没有在LINQ查询中使用它。我在编辑的问题中编写比较器的用法。 – Dejan

+0

只需用反射调用Equals方法,它就可以工作。如果您需要帮助,请写信,我会编辑答案。 – LueTm