如何从字符串表示形式获取通用类型?


79

我有MyClass<T>

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

一种方法(难看)是解析出“ <”和“>”并执行以下操作:

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

但是,有没有一种更干净的方法来获取最终类型而不进行任何解析等?

Answers:


94

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

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

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


+1-好答案,谢谢!我在摆弄一下如何找到泛型!
marc_s 2009年

谢谢。这行得通,我必须修改代码以这种方式格式化字符串。但是,想知道是否还有一种方法可以简单地使用:“ MyClass <AnotherClass>”确切地显示在字符串中以获取Type实例。看起来更干净。
DeeStackOverflow

您无需修改​​代码即可以这种方式设置字符串格式,只需在Type上调用ToString()即可。
Rush Frisby 2014年

38

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

Activator.CreateInstance(typeof(MyType))

或使用程序集并输入名称为 string

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

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

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

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

那会给你有Type问题的。


3
这只是获取类型的实例,而不是System.Type实例,它是基于代码片段的,这似乎是OP所寻找的。
丹尼尔·谢弗

26

我需要这样的东西,最终我写了一些代码来解析所需的简单类型名称。当然有改进的余地,因为它不会识别泛型类型的名称,如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);
  }
}

使用它就像编写此代码一样简单:

Type t;

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

1
简短,完美,极其有用!谢谢
xrnd 2014年

3

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

Type mytype = Type.GetType(typeName);

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

Activator.CreateInstance(mytype);

0

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

实体框架通用存储库错误

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

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

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.