C# 如何从字符串表示中获取泛型类型?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/721870/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-04 22:30:22  来源:igfitidea点击:

How can I get generic Type from a string representation?

c#reflectiontypes

提问by DeeStackOverflow

I have MyClass<T>.

我有MyClass<T>

And then I have this string s = "MyClass<AnotherClass>";. How can I get Type from the string s?

然后我有这个string s = "MyClass<AnotherClass>";。如何从字符串中获取 Type s

One way (ugly) is to parse out the "<" and ">" and do:

一种方法(丑陋)是解析“<”和“>”并执行:

Type acType = Type.GetType("AnotherClass");  
Type whatIwant = typeof (MyClass<>).MakeGenericType(acType);

But is there a cleaner way to get the final type without any parsing, etc.?

但是有没有更简洁的方法来获得最终类型而不进行任何解析等?

采纳答案by Neil Williams

The format for genericsis the name, a ` character, the number of type parameters, followed by a comma-delimited list of the types in brackets:

泛型格式是名称、` 字符、类型参数的数量,然后是括号中以逗号分隔的类型列表:

Type.GetType("System.Collections.Generic.IEnumerable`1[System.String]");

I'm not sure there's an easy way to convert from the C# syntax for generics to the kind of string the CLR wants. I started writing a quick regex to parse it out like you mentioned in the question, but realized that unless you give up the ability to have nested generics as type parameters the parsing will get very complicated.

我不确定是否有一种简单的方法可以将泛型的 C# 语法转换为 CLR 想要的字符串类型。我开始编写一个快速的正则表达式来解析它,就像您在问题中提到的那样,但意识到除非您放弃将嵌套泛型作为类型参数的能力,否则解析将变得非常复杂。

回答by marc_s

Check out Activator.CreateInstance- you can call it with a type

签出Activator.CreateInstance- 您可以使用类型调用它

Activator.CreateInstance(typeof(MyType))

or with an assembly and type name as string

或使用程序集和类型名称作为 string

Activator.CreateInstance("myAssembly", "myType")

This will give you an instance of the type you need.

这将为您提供所需类型的实例。

If you need the Typerather than the instance, use the Type.GetType()method and the fully qualified name of the type you're interested in, e.g.:

如果您需要的是Type而不是实例,请使用Type.GetType()您感兴趣的方法和类型的完全限定名称,例如:

string s = "System.Text.StringBuilder";
Type myClassType = Type.GetType(s);

That'll give you the Typein question.

那会给你Type问题。

回答by Jeff Ancel

I don't have much time to parse through this, though I think I have seen some similar answers. In particular, I think they are doing exactly what you want to do here:

我没有太多时间来解析这个,尽管我想我已经看到了一些类似的答案。特别是,我认为他们正在做你想做的事情:

Entity Framework Generic Repository Error

实体框架通用存储库错误

(String.Format("[{0}]", baseType.Name.ToString())).OfType<T>();

Hopefully this helps, let me know more specifically if this isn't.

希望这会有所帮助,如果不是,请让我更具体地知道。

回答by Turnor

To just get the type object from the string, use:

要从字符串中获取类型对象,请使用:

Type mytype = Type.GetType(typeName);

You can then pass this to Activator.CreateInstance():

然后,您可以将其传递给Activator.CreateInstance()

Activator.CreateInstance(mytype);

回答by Phillippe Santana

I've needed something like this and I ended up writing some code to parse the simple type names I needed. Of course there is room for improvement, as it will not identify generic type names like List<string>, but it does just fine for string, int[], decimal?and such. Sharing in case this helps anyone.

我需要这样的东西,最后我写了一些代码来解析我需要的简单类型名称。当然有改进的余地,因为它不会识别泛型类型的名称,如List<string>,但它确实蛮好的stringint[]decimal?和这样的。分享以防这对任何人都有帮助。

public static class TypeExtensions
{
  public static Type GetTypeFromSimpleName(string typeName)
  {
    if (typeName == null)
      throw new ArgumentNullException("typeName");

    bool isArray = false, isNullable = false;

    if (typeName.IndexOf("[]") != -1)
    {
      isArray = true;
      typeName = typeName.Remove(typeName.IndexOf("[]"), 2);
    }

    if (typeName.IndexOf("?") != -1)
    {
      isNullable = true;
      typeName = typeName.Remove(typeName.IndexOf("?"), 1);
    }

    typeName = typeName.ToLower();

    string parsedTypeName = null;
    switch (typeName)
    {
      case "bool":
      case "boolean":
        parsedTypeName = "System.Boolean";
        break;
      case "byte":
        parsedTypeName = "System.Byte";
        break;
      case "char":
        parsedTypeName = "System.Char";
        break;
      case "datetime":
        parsedTypeName = "System.DateTime";
        break;
      case "datetimeoffset":
        parsedTypeName = "System.DateTimeOffset";
        break;
      case "decimal":
        parsedTypeName = "System.Decimal";
        break;
      case "double":
        parsedTypeName = "System.Double";
        break;
      case "float":
        parsedTypeName = "System.Single";
        break;
      case "int16":
      case "short":
        parsedTypeName = "System.Int16";
        break;
      case "int32":
      case "int":
        parsedTypeName = "System.Int32";
        break;
      case "int64":
      case "long":
        parsedTypeName = "System.Int64";
        break;
      case "object":
        parsedTypeName = "System.Object";
        break;
      case "sbyte":
        parsedTypeName = "System.SByte";
        break;
      case "string":
        parsedTypeName = "System.String";
        break;
      case "timespan":
        parsedTypeName = "System.TimeSpan";
        break;
      case "uint16":
      case "ushort":
        parsedTypeName = "System.UInt16";
        break;
      case "uint32":
      case "uint":
        parsedTypeName = "System.UInt32";
        break;
      case "uint64":
      case "ulong":
        parsedTypeName = "System.UInt64";
        break;
    }

    if (parsedTypeName != null)
    {
      if (isArray)
        parsedTypeName = parsedTypeName + "[]";

      if (isNullable)
        parsedTypeName = String.Concat("System.Nullable`1[", parsedTypeName, "]");
    }
    else
      parsedTypeName = typeName;

    // Expected to throw an exception in case the type has not been recognized.
    return Type.GetType(parsedTypeName);
  }
}

Using it is as simple as writing this:

使用它就像写这个一样简单:

Type t;

t = TypeExtensions.GetTypeFromSimpleName("string");
t = TypeExtensions.GetTypeFromSimpleName("int[]");
t = TypeExtensions.GetTypeFromSimpleName("decimal?");