Instancing a class with an internal constructor
C#.NetReflectionC# Problem Overview
I have a class whose constructor is defined as internal, which means I cannot instantiate it. While that may make sense, I would still like to do it once for debugging and research purposes.
Is it possible to do so with Reflection? I know I can access Private/Internal Members, but can I call an internal constructor?
Or, as the constructor does nothing important, can I use reflection to say "Look, just give me an instance of the class without calling the constructor, I'll do it's work manually"?
Performance and "Stability" is not an issue here, as it's not production code.
Edit: Just as clarification: Sadly, I don't control the other assembly and don't have it's source code, I merely try to understand how it works as it's documentation is next to non-existent, but I am supposed to interface with it.
C# Solutions
Solution 1 - C#
An alternative would be to nominate the calling assembly as a "friend" assembly.
Simply add this to AssemblyInfo.cs file of the assembly containing the internal constructor:
[assembly: InternalsVisibleTo("Calling.Assembly")]
If you don't have access to the assembly, you can also call the constructor directly (using Reflection):
MyClass obj = (MyClass) typeof(MyClass).GetConstructor(
BindingFlags.NonPublic | BindingFlags.Instance,
null, Type.EmptyTypes, null).Invoke(null);
Solution 2 - C#
This is a method derived from this answer:
public static T CreateInstance<T>(params object[] args)
{
var type = typeof (T);
var instance = type.Assembly.CreateInstance(
type.FullName, false,
BindingFlags.Instance | BindingFlags.NonPublic,
null, args, null, null);
return (T) instance;
}
Example usage (this is a Kinect SDK type that I needed to create for unit tests):
DiscreteGestureResult a = CreateInstance<DiscreteGestureResult>(false, false, 0.5f);
Solution 3 - C#
A FormatterServices.GetUninitializedObject method exists (Namespace: System.Runtime.Serialization), it supposedly calls no constructors, if you really want to try out that approach.
Solution 4 - C#
If you want to avoid reflection, you can use expressions. Here is an example of calling a private constructor with a string value.
private static Func<string, T> CreateInstanceFunc()
{
var flags = BindingFlags.NonPublic | BindingFlags.Instance;
var ctor = typeof(T).GetConstructors(flags).Single(
ctors =>
{
var parameters = ctors.GetParameters();
return parameters.Length == 1 && parameters[0].ParameterType == typeof(string);
});
var value = Expression.Parameter(typeof(string), "value");
var body = Expression.New(ctor, value);
var lambda = Expression.Lambda<Func<string, T>>(body, value);
return lambda.Compile();
}
Solution 5 - C#
I experienced this same situation a while back and created a small utility I called "InternalsVisibleToInjector". It uses ILDASM and ILASM to disassemble, modify, and reassemble and assembly with the assembly name of my selection added to the InternalsVisibleTo list for the target assembly. It worked quite well in my situation.
I have posted the source code (VS 2008 C# WinForm) for the utility here:
http://www.schematrix.com/downloads/InternalsVisibleToInjector.zip
This may not work if the assembly is signed. Please take all appropriate precautions (i.e. make a backup of the assembly before using this and ensure you are on solid legal ground, etc.)
Solution 6 - C#
Here is a more practical example. I want to instantiate a ObjectMaterializedEventArg
from Entity Framework. It looks like this:
namespace System.Data.Entity.Core.Objects
{
/// <summary>EventArgs for the ObjectMaterialized event.</summary>
public class ObjectMaterializedEventArgs : EventArgs
{
private readonly object _entity;
internal ObjectMaterializedEventArgs(object entity)
{
this._entity = entity;
}
/// <summary>Gets the entity object that was created.</summary>
/// <returns>The entity object that was created.</returns>
public object Entity
{
get { return this._entity; }
}
}
}
As we we see, this event arg sports only an internal constructor.
To make a unit test to a patient decrypting rule in the software system I work with, we need to instantiate such an object, so I ended up using the GetConstructors
method instead.
[Test]
public void EmptyNameAndOfficialIdDoesNotThrow()
{
var patientDecryptingRule = new PatientDecryptingRule();
object[] reservation = new object[]
{
new Operation
{
Status = (int) OperationStatusDataContract.Reservation,
Patient = new Patient
{
Name = null,
OfficialId = null,
IsPatientEncrypted = true
}
}
};
var relevantConstructor = typeof(ObjectMaterializedEventArgs).GetConstructors(
BindingFlags.NonPublic | BindingFlags.Instance).FirstOrDefault();
ObjectMaterializedEventArgs objectMaterializedEventArgs =
(ObjectMaterializedEventArgs) relevantConstructor?.Invoke(reservation);
patientDecryptingRule.ModifyObjectMaterialized(objectMaterializedEventArgs);
}
I use GetConstructors
here, specifying that the constructor to look for is non public (internal for example) and instance as bindingflags
, then use FirsOrDefault
.
Hope this scenario is helpful to some that have trouble getting GetConstructor
correct. You can use GetConstructors
instead and filter some more if necessary. Then in the ?.Invoke()
pass in the object array of your parameters.
Solution 7 - C#
In case anyone stumbles across this again, here's an example of how to raise it via reflection:
var args = FormatterServices.GetUninitializedObject(typeof(SizeChangedEventArgs)) as SizeChangedEventArgs;
Debug.Assert(args != null);
var field = typeof(SizeChangedEventArgs).GetField("_previousSize", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(field != null);
field.SetValue(args, new Size(0,0));
field = typeof(SizeChangedEventArgs).GetField("_element", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(field != null);
field.SetValue(args, GraphicsWrapper);
field = typeof(RoutedEventArgs).GetField("_source", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(field != null);
field.SetValue(args, GraphicsWrapper);
field = typeof(RoutedEventArgs).GetField("_routedEvent", BindingFlags.Instance | BindingFlags.NonPublic);
Debug.Assert(field != null);
field.SetValue(args, SizeChangedEvent);
GraphicsWrapper.RaiseEvent(args);
...where the GraphicsWrapper
is the WPF control you want it raised from.
Solution 8 - C#
You could use Reflector to analyse its source code and from that figure out the inner workings.
Solution 9 - C#
internal
doesn't mean that you can't instantiate it. It just means that only members from the same assembly may call it.
For test purposes you can allow your test assembly to access internals as well using the InternalsVisibleTo attribute. See http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx