[英]Create instance of generic class with dynamic generic type parameter
I need to create instance of a generic class like this: 我需要创建一个通用类的实例,如下所示:
Type T = Type.GetType(className).GetMethod(functionName).ReturnType;
var comparer = new MyComparer<T>(); // ERROR: "The type or namespace name 'T' could not be found"
I found this answer where this is possible only with reflection. 我找到了这个答案 ,只有通过反射才能做到。 But using reflection I get object which I need to cast to my generic type. 但是使用反射,我得到了需要转换为通用类型的对象。 I tried like this 我尝试过这样
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"
but get the same error. 但得到同样的错误。 How to solve it? 怎么解决呢?
Here is a complete example: 这是一个完整的示例:
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);
}
The idea is to make a unit test which will call a function with parameters and compare its result with the correct result. 想法是进行单元测试,该单元测试将调用带有参数的函数并将其结果与正确的结果进行比较。 But I need custom comparer, so I implement MyComparer
which I cannot use because of a compiler error. 但是我需要自定义比较器,因此我实现了MyComparer
,由于编译器错误,我无法使用它。
public class MyComparer<T> : IEqualityComparer<T>
{
public bool Equals(T x, T y){/* some implementation*/}
}
I found very simple solution to problem. 我找到了解决问题的简单方法。 There is no need to cast object
to specific type T
, just use dynamic
keyword instead of casting 无需将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
and then I can use comparer normally to call its methods like: 然后我可以正常使用比较器来调用其方法,例如:
return comparer.Equals(myResultAsT, correctResultAsT);
According to LueTm comments, it is probably possible to use reflection again and call comparer methods, but this solution looks much easier. 根据LueTm的评论,可能可以再次使用反射并调用比较器方法,但是此解决方案看起来容易得多。
Looks like you're almost there: 看来您快要到了:
// 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;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.