Instancing a class with an internal constructor

C#.NetReflection

C# 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

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionMichael StumView Question on Stackoverflow
Solution 1 - C#Philippe LeybaertView Answer on Stackoverflow
Solution 2 - C#westonView Answer on Stackoverflow
Solution 3 - C#Kenan E. K.View Answer on Stackoverflow
Solution 4 - C#Xavier JohnView Answer on Stackoverflow
Solution 5 - C#Michael A. McCloskeyView Answer on Stackoverflow
Solution 6 - C#Tore AurstadView Answer on Stackoverflow
Solution 7 - C#outbredView Answer on Stackoverflow
Solution 8 - C#Peter LillevoldView Answer on Stackoverflow
Solution 9 - C#Brian RasmussenView Answer on Stackoverflow