Instantiating a constructor with parameters in an internal class with reflection
C#ReflectionC# Problem Overview
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?
C# Solutions
Solution 1 - C#
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 public
visibility; 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)
Solution 2 - C#
(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 anobject[]
as a single parameter of method that takes aparams object[]
argument - the
BindingFlags
helps resolve the non-public constructor
(the two null
s relate to the binder; the default binder behaviour is fine for what we want)
Solution 3 - C#
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:
- Call
typeToInstantiate.GetConstructor()
, passingBindingFlags.NonPublic
- Call
ConstructorInfo.Invoke
, passing it the constructor parameter
Solution 4 - C#
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