Activator.CreateInstance - How to create instances of classes that have parameterized constructors
Asked Answered
D

5

34

I have read a few bits and bobs online about this topic but found none that work for me. What I am trying to do is create a class of a runtime Type.

I use Activator.CreateInstance which works fine for classes with constructors that contain no arguments. For those with arguments it throws an exception, is there a way around this?

I am more than happy to pass null values or empty values to the ctor so long as I can create the class itself.

Dalmatian answered 17/8, 2009 at 14:37 Comment(4)
Question is not a duplicate, but answers are: #731952Ingham
possible duplicate of How to Pass Parameters to Activator.CreateInstance<T>()Bondswoman
@JimG. how can this be a duplicate of a question asked 8 months later?Loggerhead
@Yaur: Technically, you're correct; but I'd prefer to close this question because the answers to the other question are more current.Bondswoman
D
8

I eventually ended up doing something like this - some of the commentors hinted towards this solution anyway.

I basically iterated through all available constructors and chose the simplest. I then created null data to pass into the ctor (for what Im using it for this approach is fine)

Part of the code looks a little like this

// If we have a ctor that requires parameters then pass null values
if (requiresParameters)
{
    List<object> parameters = new List<object>();
    ParameterInfo[] pInfos = constructorInfos[0].GetParameters();

    foreach (ParameterInfo pi in pInfos)
    {
        parameters.Add(createType(pi.ParameterType));
    }

    return constructorInfos[0].Invoke(parameters.ToArray());
}
Dalmatian answered 19/8, 2009 at 10:25 Comment(1)
constructorInfos[0].GetParameters().Select(pi => createType(pi.ParameterType)).ToArray()Pohai
S
52

There is an overload that accepts arguments as a params object[]:

object obj = Activator.CreateInstance(typeof(StringBuilder), "abc");

Would this do? Alternative, you can use reflection to find the correct constructor:

Type[] argTypes = new Type[] {typeof(string)};
object[] argValues = new object[] {"abc"};
ConstructorInfo ctor = typeof(StringBuilder).GetConstructor(argTypes);
object obj = ctor.Invoke(argValues);
Sparhawk answered 17/8, 2009 at 14:41 Comment(4)
Just out of curiosity, which would be better from performance point of view: getting the list of constructors and invoking a particular constructor through reflection or directly calling Activator.CreateInstance with object[]?Carving
I expect the ConstructorInfo approach. Otherwise it has to think about what values are compatible with which constructors - especially if you have passed "null" etc (which might match multiple constructors).Sparhawk
But you could time it ;-p Actually, if performance is an important consideration, you could case a pre-compiled LINQ Expression (since this is .NET 3.5) that represents the constructor. Let me know if you want an example of this.Sparhawk
@MarcGravell I've just tested it. CreateInstance is slower. i.stack.imgur.com/kffhE.pngWhist
D
8

I eventually ended up doing something like this - some of the commentors hinted towards this solution anyway.

I basically iterated through all available constructors and chose the simplest. I then created null data to pass into the ctor (for what Im using it for this approach is fine)

Part of the code looks a little like this

// If we have a ctor that requires parameters then pass null values
if (requiresParameters)
{
    List<object> parameters = new List<object>();
    ParameterInfo[] pInfos = constructorInfos[0].GetParameters();

    foreach (ParameterInfo pi in pInfos)
    {
        parameters.Add(createType(pi.ParameterType));
    }

    return constructorInfos[0].Invoke(parameters.ToArray());
}
Dalmatian answered 19/8, 2009 at 10:25 Comment(1)
constructorInfos[0].GetParameters().Select(pi => createType(pi.ParameterType)).ToArray()Pohai
G
2

I'm using this method to get around an issue I ran into, and it seems to be working exactly as I hoped. :)

object instance = Activator.CreateInstance(
    typeof(OpCode),
    BindingFlags.NonPublic | BindingFlags.Instance,
    default(Binder),
    new object[] { stringname, pop, push, operand, type, size, s1, s2, ctrl, endsjmpblk, stack },
    default(CultureInfo));
Geyer answered 19/8, 2009 at 10:47 Comment(1)
Can that be used on any type...?Dalmatian
R
0

Activator.CreateInstance also has a whole bunch of overloads, one you might want to check out is ( Type type, params object[] args ). Simply supply the required constructor arguments to the second parameter of this call.

Make sure you handle exceptions here though, as it's easy to pass incorrect parameters in or for something to change in the type's constructors later on that breaks it..

Riant answered 17/8, 2009 at 14:44 Comment(0)
L
0

As an alternative to Activator.CreateInstance, FastObjectFactory in the linked url preforms better than Activator (as of .NET 4.0 and significantly better than .NET 3.5. No tests/stats done with .NET 4.5). See StackOverflow post for stats, info and code. Note that some modifications may need to be done based upon the number of ctor params. The code provided only allows 1 ctor param but can be modified to have more than 1. See comments in code.

How to pass ctor args in Activator.CreateInstance or use IL?

Lette answered 22/1, 2014 at 21:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.