55

I have a table in my database that I use to manage relationships across my application. it's pretty basic in it's nature - parentType,parentId, childType, childId... all as ints. I've done this setup before, but I did it with a switch/case setup when I had 6 different tables I was trying to link. Now I have 30 tables that I'm trying to do this with and I would like to be able to do this without having to write 30 case entries in my switch command.

Is there a way that I can make reference to a .Net class using a string? I know this isn't valid (because I've tried several variations of this):

Type t = Type.GetType("WebCore.Models.Page");
object page = new t();

I know how to get the Type of an object, but how do I use that on the fly to create a new object?

6 Answers 6

73

This link should help:
https://learn.microsoft.com/en-us/dotnet/api/system.activator.createinstance

Activator.CreateInstance will create an instance of the specified type.

You could wrap that in a generic method like this:

public T GetInstance<T>(string type)
{
    return (T)Activator.CreateInstance(Type.GetType(type));
}
Sign up to request clarification or add additional context in comments.

7 Comments

This will not work if the assembly containing the type is not already loaded into the AppDomain.
Also in order to call that method then the OP must have access to the type at compile time - the original question asked how to create an instance at execution time from a string.
i am merely basing my answer on the example provided in the question.
Ah you are right - OP does appear to have access to the type! My mistake - (-1) removed!
Your example would require knowledge of the type at compile time as well :)
|
16
public static T GetInstance<T>(params object[] args)
{
     return (T)Activator.CreateInstance(typeof(T), args);
}

I would use Activator.CreateInstance() instead of casting, as the Activator has a constructor for generics.

Comments

15

If the type is known by the caller, there's a better, faster way than using Activator.CreateInstance: you can instead use a generic constraint on the method that specifies it has a default parameterless constructor.

Doing it this way is type-safe and doesn't require reflection.

T CreateType<T>() where T : new()
{
   return new T();
}

2 Comments

It doesn't require reflection at the source code level - it uses Activator.CreateInstance in the generated IL though.
reflection is required because the OP specified using a string to identify the Type.
8

You want to use Activator.CreateInstance.

Here is an example of how it works:

using System;
using System.Runtime.Remoting;

class Program
{
    static void Main()
    {
        ObjectHandle o = Activator.CreateInstance("mscorlib.dll", "System.Int32");

        Int32 i = (Int32)o.Unwrap();
    }
}

Comments

1

Assuming you have the following type:

public class Counter<T>
{
  public T Value { get; set; }
}

and have the assembly qualified name of the type, you can construct it in the following manner:

string typeName = typeof(Counter<>).AssemblyQualifiedName;
Type t = Type.GetType(typeName);

Counter<int> counter = 
  (Counter<int>)Activator.CreateInstance(
    t.MakeGenericType(typeof(int)));

counter.Value++;
Console.WriteLine(counter.Value);

Comments

1

Here is a function I wrote that clones a record of type T, using reflection. This is a very simple implementation, I did not handle complex types etc.

 public static T Clone<T>(T original)
    {
        T newObject = (T)Activator.CreateInstance(original.GetType());

        foreach (var prop in original.GetType().GetProperties())
        {
            prop.SetValue(newObject, prop.GetValue(original));
        }

        return newObject;
    }

I hope this can help someone.

Assaf

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.