简体   繁体   English

c# - 可以从C#类型转换为System.Type但反之亦然

[英]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. 这是因为,而intGeneric<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 ) 但即便在这里,从Typefield.FieldType )中获取另一个Typetype

There are normally three ways of using this: 通常有三种使用方法:

  • Full reflection: you use the object of type 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);
  • Interfaces/base classes: you have a non-generic base class or interface that is common between all the 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);
  • A generic method where you put all the handling of the 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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM