tags:

views:

742

answers:

4

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?

+13  A: 

This link should help:

http://msdn.microsoft.com/en-us/library/system.activator.createinstance(VS.71).aspx

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));
}
Jason Miesionczek
This will not work if the assembly containing the type is not already loaded into the AppDomain.
Andrew Hare
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.
Andrew Hare
i am merely basing my answer on the example provided in the question.
Jason Miesionczek
Ah you are right - OP does appear to have access to the type! My mistake - (-1) removed!
Andrew Hare
Your example would require knowledge of the type at compile time as well :)
Jason Miesionczek
Haha - you are right!! Very nicely done!! :)
Andrew Hare
+1 to you, by the way.
Andrew Hare
+6  A: 

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();
    }
}
Andrew Hare
+2  A: 

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();
}
Judah Himango
It doesn't require reflection at the source code level - it uses Activator.CreateInstance in the generated IL though.
Jon Skeet
reflection is required because the OP specified using a string to identify the Type.
Jason Miesionczek
A: 

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);
sduplooy