使用私有构造函数实例化内部类

sun*_*nny 25 c#

我正在尝试使用反射来创建类的实例.但它内部密封,并有私人构造.我想知道如何初始化它,作为框架的一部分,我只能用反射把它拿出来?

internal sealed class ABC
{
    private ABC(string password){}
    public static ABC Create(string password){};
}
Run Code Online (Sandbox Code Playgroud)

补充:System.ServiceModel.Channels.SelfSignedCertificate是我尝试使用的内部类

Jon*_*eet 25

编辑:我没有注意到你提到你尝试初始化的类型是.NET框架的一部分.我认为这是你自己的类型之一,只是从其他地方引用.

我强烈建议你不要这样做.微软可以自由地在框架版本之间更改或删除内部类 - 如果您依赖这样的实现细节,您的代码将非常脆弱.

更改您的设计以避免需要这样做.


原始答案:

是的,你必须使用反射 - 像这样:

using System;
using System.Reflection;

internal sealed class ABC
{
    private ABC(string password)
    {
        Console.WriteLine("Constructor called");
    }
}

public class Test
{
    static void Main()
    {
        ConstructorInfo ctor = typeof(ABC).GetConstructors
            (BindingFlags.Instance | BindingFlags.NonPublic)[0];

        ABC abc = (ABC) ctor.Invoke(new object[] { "test" });
    }
}
Run Code Online (Sandbox Code Playgroud)

请注意,以这种方式违反访问修饰符需要ReflectionPermissionFlag.MemberAccess权限.如果你知道会有一个静态方法调用Create,你最好通过反射来调用:

using System;
using System.Reflection;

internal sealed class ABC
{
    private ABC(string password)
    {
        Console.WriteLine("Constructor called");
    }

    public static ABC Create(string password)
    {
        return new ABC(password);
    }
}

public class Test
{
    static void Main()
    {
        MethodInfo method = typeof(ABC).GetMethod("Create",
            BindingFlags.Static | BindingFlags.Public);

        ABC abc = (ABC) method.Invoke(null, new object[]{"test"});
    }
}
Run Code Online (Sandbox Code Playgroud)

  • 如果 ABC 类型是另一个程序集中的内部类型,则他将需要通过其全名获取该类型。 (2认同)

ang*_*son 20

首先,它是内部的事实意味着你不应该做你想做的事情.

你应该认真地尝试找到你想要完成的替代路线.

不幸的是,你没有告诉我们你想要完成什么,只是你认为你想要做的下一步,所以这就是我可以帮助你的.

此代码将起作用,并访问公共静态方法:

Type t = typeof(SomeOtherTypeInSameAssembly)
    .Assembly.GetType("ClassLibrary1.ABC");
MethodInfo method = t.GetMethod("Create",
    BindingFlags.Public | BindingFlags.Static, null,
    new Type[] { typeof(String) },
    new ParameterModifier[0]);
Object o = method.Invoke(null, new Object[] { "test" });
Run Code Online (Sandbox Code Playgroud)

请注意,这依赖于访问同一程序集中的另一个类型,即public.如果没有,则需要获取包含该类型的Assembly对象.

  • 事实上有人需要访问内部类并且知道特定的内部类实际上表明他们可能足够聪明地打开Reflector并自己决定这样做是否有用或者是个好主意.代码是代码,"内部"修饰符只不过是一种被规避的DRM,即IMO. (19认同)
  • "首先,它是内部的事实意味着你不应该做你想做的事情.那么进行单元测试但保持类隔离呢? (7认同)
  • @ktutnik:通过单元测试,这通常通过[InternalsVisibleToAttribute]实现(http://msdn.microsoft.com/en-us/library/system.runtime.compilerservices.internalsvisibletoattribute.aspx) (4认同)