Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Dynamic class initialization in .NET

Tags:

c#

reflection

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.

like image 627
ryeguy Avatar asked Dec 08 '22 06:12

ryeguy


1 Answers

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.

like image 121
Jon Skeet Avatar answered Jan 03 '23 08:01

Jon Skeet