使用内部构造函数对类进行实例化

Mic*_*tum 47 .net c# reflection

我有一个类,其构造函数被定义为内部,这意味着我无法实例化它.虽然这可能有意义,但我仍然希望这样做一次用于调试和研究目的.

用反射可以做到吗?我知道我可以访问私人/内部成员,但我可以调用内部构造函数吗?

或者,由于构造函数没有什么重要的,我可以使用反射来说"看,只需给我一个类的实例而不调用构造函数,我会手动完成它的工作"?

性能和"稳定性"在这里不是问题,因为它不是生产代码.

编辑:正如澄清:遗憾的是,我不控制其他程序集并且没有它的源代码,我只是试图理解它是如何工作的,因为它的文档旁边是不存在的,但我应该与它.

Phi*_*ert 85

另一种方法是将调用程序集指定为"朋友"程序集.

只需将其添加到包含内部构造函数的程序集的AssemblyInfo.cs文件中:

[assembly: InternalsVisibleTo("Calling.Assembly")]
Run Code Online (Sandbox Code Playgroud)

如果您无权访问程序集,也可以直接调用构造函数(使用Reflection):

MyClass obj = (MyClass) typeof(MyClass).GetConstructor(
                  BindingFlags.NonPublic | BindingFlags.Instance,
                  null, Type.EmptyTypes, null).Invoke(null);
Run Code Online (Sandbox Code Playgroud)

  • 编辑我的答案以包括使用反射的解决方案 (2认同)

Ken*_* K. 32

一个FormatterServices.GetUninitializedObject方法存在(命名空间:System.Runtime.Serialization),它理应唤不回构造函数,如果你真的想尝试一下这种方法.

  • 这和Type.GetField()/ FieldInfo.SetValue解决了我的问题. (3认同)

wes*_*ton 21

这是从这个答案得出的方法:

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;
}
Run Code Online (Sandbox Code Playgroud)

示例用法(这是我需要为单元测试创​​建的Kinect SDK类型):

DiscreteGestureResult a = CreateInstance<DiscreteGestureResult>(false, false, 0.5f);
Run Code Online (Sandbox Code Playgroud)


Xav*_*ohn 5

如果想避免反射,可以使用表达式。下面是使用字符串值调用私有构造函数的示例。

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();
}
Run Code Online (Sandbox Code Playgroud)

  • 这如何避免反射?`typeof(T).GetConstructors(flags)。` (13认同)