5

Let's say I have base class FooParent, and it has a numerous amount of FooChildren. At runtime I must create an instance of one of the FooChildren. How would I do this? I realize I could create a huge map (and use delegates) or a huge switch/case statement, but that just seems a bit sloppy. In something like PHP, I can easily create a class dynamically like this:

$className="FooClass";
$myNewFooClass=new $className; //makes a new instance of FooClass

(you can also do this using reflection).

Does .NET have anything like this? Is reflection an option, and does it have any performance penalties? If not, what other options do I have?

The type of class will be determined by a JSON request. The variable could be anything I want..it could be an integer if I wanted to do an enum, or it could be the full class name. I haven't created it yet so I'm undecided.

2
  • Look up "Activator.CreateInstance". Commented Aug 15, 2009 at 19:41
  • Will the class always have a parameterless constructor? Commented Aug 15, 2009 at 20:11

4 Answers 4

10

You can do it with reflection if you really want, but there will be performance penalties. Whether they're significant or not will depend on your exact situation.

Depending on exactly what you want to do, I'd quite possibly go with either a switch/case statement or a map, as you suggest. In particular, that would be useful if you need to pass different arguments to different constructors based on the type you're constructing - doing that via reflection would be a bit of a pain in that you'd already be special-casing different types.


EDIT: Okay, so we now know that there will always be a parameterless constructor. In that case, your JSON could easily contain the class name without the namespace (if they're all in the same namespace) and your method could look something like this:

public FooParent CreateFoo(string name)
{
    if (name == null)
    {
        throw new ArgumentNullException("name");
    }
    string fullName = "Some.NameSpace." + name;
    // This is assuming that the type will be in the same assembly
    // as the call. If that's not the case, we can look at that later.
    Type type = Type.GetType(fullName);
    if (type == null)
    {
        throw new ArgumentException("No such type: " + type);
    }
    if (!typeof(FooParent).IsAssignableFrom(type))
    {
        throw new ArgumentException("Type " + type +
                                    " is not compatible with FooParent.");
    }
    return (FooParent) Activator.CreateInstance(type);
}

Where do you determine the name to use? If it's passed in somewhere, a switch statement can be very simple when reformatted away from the norm a little:

public FooParent CreateFoo(string name)
{
    switch (name)
    {
        case "Foo1":      return new Foo1();
        case "Foo2":      return new Foo2();
        case "Foo3":      return new Foo3();
        case "Foo4":      return new Foo4();
        case "FooChild1": return new FooChild1();
        default:
            throw new ArgumentException("Unknown Foo class: " + name);
    }
}

Mind you, having just written that out I'm not sure it has any real benefit (other than performance) over using Type.GetType(name) and then Activator.CreateInstance(type).

How does the caller know the class name to pass in? Will that definitely be dynamic? Is there any chance you could use generics? The more you could tell us about the situation, the more helpful we could be.

Sign up to request clarification or add additional context in comments.

1 Comment

Yes, the class will always have a paramaterless constructor.
4

As long as all your FooChildren have parameterless constructors, you can do this with reflection.

Activator.CreateInstance<FooChildType>();

If you don't actually have a reference to the type, and all you have is a string with the name of the class, you can do:

Activator.CreateInstance("FooChildClassName", "Fully.Qualified.AssemblyName");

There is a performance penalty with reflection, but I wouldn't get hung up about it if this turns out to be the simplest solution for you, and your performance is acceptable.

Comments

3
yourvar = Activator.CreateInstance(Type.GetType("foo.bar.Baz"));

Comments

1

If you care about performance, there is another option. Use

Type yourType = Type.GetType("FooClass");

to get the type of your class. Now you can use

ConstructorInfo ctor = yourType.GetConstructor(new Type[0]);

to get the constructor info for your constructor. If you don't want the default constructor, pass an array of the types you want to pass to the constructor. Now you can use the constructor like this:

object instanceOfFooClass = ctor.Invoke(new object[0]);

The first two steps have to be executed only once. You can save "ctor" for further use. That should be faster that calling Activator.CreateInstance.

1 Comment

according to this blog from 2010, it is faster to use activator for default construction. IMO, Activator looks better.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.