[英]c# - can convert from C# type to System.Type but not vice-versa
I can create a generic class that takes, as its template parameter, a C# type, and then within the generic class use the System.Type information corresponding to that C# type: 我可以创建一个泛型类,它将C#类型作为模板参数,然后在泛型类中使用与该C#类型对应的System.Type信息:
public class Generic<T>
{
public bool IsArray()
{
return typeof(T).IsArray();
}
public T Create()
{
return blah();
}
}
Generic<int> gi = new Generic<int>();
Debug.WriteLine("int isarray=" + gi.IsArray());
Generic<DateTime> gdt;
But now let's say what I have, is a System.Type. 但现在让我们说我拥有的是System.Type。 I can't use this to instantiate my generic class: 我无法使用它来实例化我的泛型类:
FieldInfo field = foo();
Generic<field.FieldType> g; // Not valid!
Is there some clever C# thing I can do, to convert a System.Type back to the original C# type? 我可以做一些聪明的C#,将System.Type转换回原来的C#类型吗? Or some other way, to create a generic that can (1) give me information about the System.Type, and (2) create objects of the associate C# type? 或者其他一些方法,创建一个可以(1)给我关于System.Type的信息的通用,以及(2)创建关联C#类型的对象?
By the way, this is a very contrived example to explain the problem I'm trying to solve, don't worry too much about whether Generic makes sense or not! 顺便说一句,这是一个非常人为的例子来解释我试图解决的问题,不要太担心Generic是否有意义!
The only thing you can do is use reflection. 你唯一能做的就是使用反射。 This because while the int
of Generic<int>
is known at compile-time, the field.FieldType
is known only at runtime. 这是因为,而int
的Generic<int>
是在编译时已知的, field.FieldType
仅在运行时是已知的。
Reflection example: 反思例子:
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
// Object of type Generic<field.FieldType>
object gen = Activator.CreateInstance(type);
But even here, from a Type
( field.FieldType
) you obtain another Type
( type
) 但即便在这里,从Type
( field.FieldType
)中获取另一个Type
( type
)
There are normally three ways of using this: 通常有三种使用方法:
Generic<type>
only through reflection. 完全反射:您只能通过反射使用Generic<type>
类型的对象。 You create it through Activator.CreateInstance
and from there you begin using Type.GetMethod()
and Invoke()
你通过Activator.CreateInstance
创建它,然后从那里开始使用Type.GetMethod()
和Invoke()
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
// Object of type Generic<field.FieldType>
object gen = Activator.CreateInstance(type);
MethodInfo isArray = type.GetMethod("IsArray");
bool result = (bool)isArray.Invoke(gen, null);
Generic<T>
. 接口/基类:你有一个非通用的基类或接口,它在所有Generic<T>
之间是Generic<T>
。 You use your object only though that interface/base class. 您只能通过该接口/基类使用您的对象。 public class Generic<T> : IComparable where T : new()
{
public bool IsArray()
{
return typeof(T).IsArray;
}
public T Create()
{
return new T();
}
public int CompareTo(object obj)
{
return 0;
}
}
Type type = typeof(Generic<>).MakeGenericType(field.FieldType);
IComparable cmp = (IComparable)Activator.CreateInstance(type);
int res = cmp.CompareTo(cmp);
Generic<T>
. 一种通用方法,您可以对Generic<T>
所有处理。 That is the only method that is used through reflection. 这是通过反射使用的唯一方法。 public static void WorkWithT<T>() where T : new()
{
Generic<T> g = new Generic<T>();
T obj = g.Create();
Console.WriteLine(g.IsArray());
}
var method = typeof(Program).GetMethod("WorkWithT").MakeGenericMethod(field.FieldType);
// Single reflection use. Inside WorkWithT no reflection is used.
method.Invoke(null, null);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.