62

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.

Michael Stum
  • 177,530
  • 117
  • 400
  • 535

9 Answers9

99

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);
Philippe Leybaert
  • 168,566
  • 31
  • 210
  • 223
38

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);
Community
  • 1
  • 1
weston
  • 54,145
  • 21
  • 145
  • 203
33

A FormatterServices.GetUninitializedObject method exists (Namespace: System.Runtime.Serialization), it supposedly calls no constructors, if you really want to try out that approach.

jakobbg
  • 174
  • 3
  • 12
Kenan E. K.
  • 13,955
  • 3
  • 43
  • 48
  • 4
    This and Type.GetField()/FieldInfo.SetValue solved my problem. – Michael Stum Jul 29 '09 at 12:16
  • @Kenan : risky if the constructor take arguments and operate on those arguments is better use reflection and call it, instead of create an unitialized object and replicate constructor behavoiour from the instance "outside" using reflection. Seems to me that Tore solution is better. – Skary Dec 27 '20 at 15:34
5

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();
}
Wai Ha Lee
  • 8,598
  • 83
  • 57
  • 92
Xavier John
  • 8,474
  • 3
  • 37
  • 51
3

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.)

Michael A. McCloskey
  • 2,391
  • 16
  • 19
3

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.

Nahuel Ianni
  • 3,177
  • 4
  • 23
  • 30
Tore Aurstad
  • 3,189
  • 1
  • 27
  • 22
2

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.

Martin Prikryl
  • 188,800
  • 56
  • 490
  • 992
outbred
  • 1,028
  • 8
  • 13
  • B/c...it is impossible to call an internal ctor. Hence the above example. Using the FormatterServices.GetUninitializedObject() method in the ACCEPTED answer, you bypass this restriction. – outbred Mar 05 '17 at 05:45
  • Sorry, I was not paying attention. +1 – Martin Prikryl Mar 05 '17 at 06:45
1

You could use Reflector to analyse its source code and from that figure out the inner workings.

Peter Lillevold
  • 33,668
  • 7
  • 97
  • 131
  • 1
    @AdamPlocher - lol yourself. The OP clearly states that " I merely try to understand how it works". Reverse engineering the code from IL is, imho, a very viable way of understanding code. I would say that, in order to understand the inner workings of some assembly, it is easier to read the code, than to trying to poke an instance in runtime. So my answer stands, downvoted or not. – Peter Lillevold Jul 25 '14 at 08:16
  • And @AdamPlocher: my 5 year old answer is as old as all the other answers to this question. Hey, even the question is 5 years old! So whats up with that? – Peter Lillevold Jul 25 '14 at 08:20
0

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

Brian Rasmussen
  • 114,645
  • 34
  • 221
  • 317
  • 2
    Er.. what if you want to instantiate it from another assembly. Then you can't.... – cjk Jul 29 '09 at 11:38
  • Correct, unless you can use the InternalsVisibleTo. With the update to the question that doesn't seem to be the case, but that was not clear to me from the original wording. – Brian Rasmussen Jul 29 '09 at 12:25