224

If I receive a string that contains the name of a class and I want to convert this string to a real type (the one in the string), how can I do this?

I tried

Type.GetType("System.Int32")

for example, it appears to work.

But when I try with my own object, it always returns null ...

I have no idea what will be in the string in advance so it's my only source for converting it to its real type.

Type.GetType("NameSpace.MyClasse");

Any idea?

vinhent
  • 2,692
  • 4
  • 17
  • 20
  • 1
    Show us your sample failed code, also show us what is original type. – Saeed Amiri Jun 19 '12 at 18:57
  • Also, tell us why/what you are trying to do. There might be a work around would would not require you to send a string representation of the type. – Trisped Jun 19 '12 at 18:58

4 Answers4

466

You can only use just the name of the type (with its namespace, of course) if the type is in mscorlib or the calling assembly. Otherwise, you've got to include the assembly name as well:

Type type = Type.GetType("Namespace.MyClass, MyAssembly");

If the assembly is strongly named, you've got to include all that information too. See the documentation for Type.GetType(string) for more information.

Alternatively, if you have a reference to the assembly already (e.g. through a well-known type) you can use Assembly.GetType:

Assembly asm = typeof(SomeKnownType).Assembly;
Type type = asm.GetType(namespaceQualifiedTypeName);
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • It works fine... the only problem I have now is when I have a System.Collections.List or IList. How can I do that ? Because I don't only want the List Type but the type the list contains. Like List by example. And remember thaht I don't know in advance what will be in the string, I just have to cast in a real Type. Is it possible ? – vinhent Jun 21 '12 at 12:14
  • @Vinhent: At that point it's tricky - you need to parse out the generic part from the type arguments, and use `Type.MakeGenericType`. Do you have any control over the format of the input? Something like `List` is a tricky name, because `string` is a C#-specific alias. – Jon Skeet Jun 21 '12 at 13:23
  • I saw one of your other post doing that : Type type = Type.GetType("System.Collections.Generic.List`1[System.String]"); it would be something like that I need. Because I receve the string and I must parse it in Type. Yes I have some control of the format of the string, but I cannot know if it will be a List, string, int, own solution objects in advance. It works well but not for List. – vinhent Jun 21 '12 at 13:26
  • @Vinhent: Well if you can get the string to be of that sort of format, that's fine, and you can just use `Type.GetType`. – Jon Skeet Jun 21 '12 at 13:32
  • Will it works for a personal pbject from my own solution ? Type.GetType("System.Collections.Generic.List`1[myClasse, assemblyName]"); ? And what the `1 is use for ? And in case is an IList it says System.Collections.IList is not a GenericTypeDefinition. MakeGenericType may only be called on a type for which Type.IsGenericTypeDefinition is true. – vinhent Jun 21 '12 at 13:37
  • @Vinhent: With the assembly name, it should work. The `1 indicates the number of type parameters. – Jon Skeet Jun 21 '12 at 13:40
  • Something like Type.GetType("System.Collections.Generic.List`1[namespace.myClass, AssemblyName]") always return null. It looks to work with System.String and System.Int32. And it doesn't work with an IList. – vinhent Jun 21 '12 at 13:50
  • 2
    @Vinhent: Just experimenting, it looks like you need to double the square brackets for fully-qualified names: `Type.GetType("System.Collections.Generic.List`1[[namespace.myClass, AssemblyName]]")` That should work with `IList` as well. – Jon Skeet Jun 21 '12 at 14:07
  • Yes it works with [[]], cool! Didn't know those things, you helped me pretty good. For the IList, I was doing System.Collections.IList and didn't work but it works with System.Collections.Generic.IList – vinhent Jun 21 '12 at 14:19
  • This is not one of my use case for now, but do you know if it would work with an array ? Something lie Type.GetType("System.String[]") ? Or "System.Array`1[[System.String]]" ? – vinhent Jun 21 '12 at 18:28
  • 5
    @Vinhent: To debug all of these cases, choose something and print out its full name, e.g. `typeof(string[]).FullName`. If you learn how to do this yourself it'll be a lot easier than asking me for each variation. – Jon Skeet Jun 21 '12 at 18:37
  • I didn't notice the that the ',' between the type name and the assembly name is inside the quotes. I was trying to pass two separate arguments and causing myself much frustration. Worse, I think this is the second time (at least) that I've done this. – Darrel Lee Jun 07 '16 at 03:04
  • *"if the type is in `System.Private.CoreLib`"* in .NET Core – Charlieface Apr 25 '23 at 15:46
43

Try:

Type type = Type.GetType(inputString); //target type
object o = Activator.CreateInstance(type); // an instance of target type
YourType your = (YourType)o;

Jon Skeet is right as usually :)

Update: You can specify assembly containing target type in various ways, as Jon mentioned, or:

YourType your = (YourType)Activator.CreateInstance("AssemblyName", "NameSpace.MyClass");
abatishchev
  • 98,240
  • 88
  • 296
  • 433
  • 8
    The point is that Type.GetType is returning null for the OP. See my answer for the most likely cause. – Jon Skeet Jun 19 '12 at 18:59
  • 1
    It works fine... the only problem I have now is when I have a System.Collections.List or IList. How can I do that ? Because I don't only want the List Type but the type the list contains. Like List by example. And remember thaht I don't know in advance what will be in the string, I just have to cast in a real Type. Is it possible ? – vinhent Jun 21 '12 at 12:15
  • Might want to note that 'inputString' needs to be full namespace as thats what through me off in comparing yours to his. – Brock Hensley Jul 19 '13 at 20:26
19

If you really want to get the type by name you may use the following:

System.AppDomain.CurrentDomain.GetAssemblies().SelectMany(x => x.GetTypes()).First(x => x.Name == "theassembly");

Note that you can improve the performance of this drastically the more information you have about the type you're trying to load.

Chris Kerekes
  • 1,116
  • 8
  • 27
  • 1
    It works fine... the only problem I have now is when I have a System.Collections.List or IList. How can I do that ? Because I don't only want the List Type but the type the list contains. Like List by example. And remember thaht I don't know in advance what will be in the string, I just have to cast in a real Type. Is it possible ? – vinhent Jun 21 '12 at 12:16
4

use following LoadType method to use System.Reflection to load all registered(GAC) and referenced assemblies and check for typeName

public Type[] LoadType(string typeName)
{
    return LoadType(typeName, true);
}

public Type[] LoadType(string typeName, bool referenced)
{
    return LoadType(typeName, referenced, true);
}

private Type[] LoadType(string typeName, bool referenced, bool gac)
{
    //check for problematic work
    if (string.IsNullOrEmpty(typeName) || !referenced && !gac)
        return new Type[] { };

    Assembly currentAssembly = Assembly.GetExecutingAssembly();

    List<string> assemblyFullnames = new List<string>();
    List<Type> types = new List<Type>();

    if (referenced)
    {            //Check refrenced assemblies
        foreach (AssemblyName assemblyName in currentAssembly.GetReferencedAssemblies())
        {
            //Load method resolve refrenced loaded assembly
            Assembly assembly = Assembly.Load(assemblyName.FullName);

            //Check if type is exists in assembly
            var type = assembly.GetType(typeName, false, true);

            if (type != null && !assemblyFullnames.Contains(assembly.FullName))
            {
                types.Add(type);
                assemblyFullnames.Add(assembly.FullName);
            }
        }
    }

    if (gac)
    {
        //GAC files
        string gacPath = Environment.GetFolderPath(System.Environment.SpecialFolder.Windows) + "\\assembly";
        var files = GetGlobalAssemblyCacheFiles(gacPath);
        foreach (string file in files)
        {
            try
            {
                //reflection only
                Assembly assembly = Assembly.ReflectionOnlyLoadFrom(file);

                //Check if type is exists in assembly
                var type = assembly.GetType(typeName, false, true);

                if (type != null && !assemblyFullnames.Contains(assembly.FullName))
                {
                    types.Add(type);
                    assemblyFullnames.Add(assembly.FullName);
                }
            }
            catch
            {
                //your custom handling
            }
        }
    }

    return types.ToArray();
}

public static string[] GetGlobalAssemblyCacheFiles(string path)
{
    List<string> files = new List<string>();

    DirectoryInfo di = new DirectoryInfo(path);

    foreach (FileInfo fi in di.GetFiles("*.dll"))
    {
        files.Add(fi.FullName);
    }

    foreach (DirectoryInfo diChild in di.GetDirectories())
    {
        var files2 = GetGlobalAssemblyCacheFiles(diChild.FullName);
        files.AddRange(files2);
    }

    return files.ToArray();
}
Ehsan Mohammadi
  • 415
  • 4
  • 15