Instantiating a constructor with parameters in an

2020-01-26 07:25发布

问题:

I have something along the lines of this:

object[] parameter = new object[1];
parameter[0] = x;
object instantiatedType =
Activator.CreateInstance(typeToInstantiate, parameter);

and

internal class xxx : ICompare<Type>
{
    private object[] x;

    # region Constructors

    internal xxx(object[] x)
    {
        this.x = x;
    }

    internal xxx()
    {
    }

    ...
}

And I get:

threw exception: System.MissingMethodException: Constructor on type 'xxxx.xxx' not found..

Any ideas?

回答1:

The issue is that Activator.CreateInstance(Type, object[]) does not consider non-public constructors.

Exceptions

MissingMethodException: No matching public constructor was found.

This is easily shown by changing the constructor to publicvisibility; the code then works correctly.

Here's one workaround (tested):

 BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
 CultureInfo culture = null; // use InvariantCulture or other if you prefer
 object instantiatedType =   
   Activator.CreateInstance(typeToInstantiate, flags, null, parameter, culture);

If you only require the parameterless constructor this will work as well:

//using the overload: public static object CreateInstance(Type type, bool nonPublic)
object instantiatedType = Activator.CreateInstance(typeToInstantiate, true)


回答2:

(tested successfully)

object instantiatedType =
   Activator.CreateInstance(typeToInstantiate,
   System.Reflection.BindingFlags.NonPublic |
     System.Reflection.BindingFlags.Instance,
   null, new object[] {parameter}, null);

There are two issues this addresses:

  • the new object[] {parameter} helps it handle the issue of passing an object[] as a single parameter of method that takes a params object[] argument
  • the BindingFlags helps resolve the non-public constructor

(the two nulls relate to the binder; the default binder behaviour is fine for what we want)



回答3:

You need to call a different overload of Activator.CreateInstance that lets you pass a nonPublic or BindingFlags parameter.

I find all these CreateInstance overloads clumsy; what I prefer to do is:

  1. Call typeToInstantiate.GetConstructor(), passing BindingFlags.NonPublic
  2. Call ConstructorInfo.Invoke, passing it the constructor parameter


回答4:

change it to

Activator.CreateInstance(typeToInstantiate,new object[] { parameter });

This is because your constructor also expects an object array and activator already splits it up into separate objects



标签: c# reflection