How can I get generic Type from a string representation?

前端 未结 5 731
没有蜡笔的小新
没有蜡笔的小新 2020-11-30 00:42

I have MyClass.

And then I have this string s = \"MyClass\";. How can I get Type from the string s

相关标签:
5条回答
  • 2020-11-30 01:28

    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(mytype);
    
    0 讨论(0)
  • 2020-11-30 01:32

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

    Activator.CreateInstance(typeof(MyType))
    

    or with an assembly and type name as string

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

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

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

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

    That'll give you the Type in question.

    0 讨论(0)
  • 2020-11-30 01:34

    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.

    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?");
    
    0 讨论(0)
  • 2020-11-30 01:37

    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.

    0 讨论(0)
  • 2020-11-30 01:44

    The format for generics is 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.

    0 讨论(0)
提交回复
热议问题