【问题标题】:How can I get generic Type from a string representation?如何从字符串表示中获取通用类型?
【发布时间】:2010-10-17 20:05:45
【问题描述】:

我有MyClass<T>

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

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

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

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

【问题讨论】:

    标签: c# reflection types


    【解决方案1】:

    format for generics 是名称、` 字符、类型参数的数量,后跟括号中以逗号分隔的类型列表:

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

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

    【讨论】:

    • +1 - 很好的答案,谢谢!我一直在摆弄试图找出如何处理泛型!
    • 谢谢。这有效,我必须修改代码以这种方式格式化字符串。但是,想知道是否还有一种方法可以简单地使用 : "MyClass" 完全按照字符串中显示的方式来获取 Type 实例。看起来干净多了。
    • 这种方式不需要修改代码来格式化字符串,只需在Type上调用ToString()即可。
    • 如果类型是不同程序集中的自定义类(不是字符串这样的类型),您将如何指定它?我尝试在 [] 中给出完全限定的程序集名称,但这不起作用。
    【解决方案2】:

    查看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

    【讨论】:

    • 这只是获取类型的一个实例,而不是 System.Type 实例,它基于代码 sn-p,似乎是 OP 正在寻找的。​​span>
    【解决方案3】:

    我需要这样的东西,最后我写了一些代码来解析我需要的简单类型名称。当然还有改进的余地,因为它不会识别像List&lt;string&gt; 这样的泛型类型名称,但它对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?");
    

    【讨论】:

    • 简短,完美,非常有用!谢谢
    【解决方案4】:

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

    Type mytype = Type.GetType(typeName);
    

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

    Activator.CreateInstance(mytype);
    

    【讨论】:

      【解决方案5】:

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

      Entity Framework Generic Repository Error

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

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

      【讨论】:

        猜你喜欢
        • 2023-03-13
        • 2017-06-13
        • 1970-01-01
        • 1970-01-01
        • 2014-01-01
        • 1970-01-01
        • 1970-01-01
        • 2011-01-25
        相关资源
        最近更新 更多