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

时间:2010-01-07 19:52:29

标签: c#

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

internal sealed class ABC
{
    private ABC(string password){}
    public static ABC Create(string password){};
}

添加了: System.ServiceModel.Channels.SelfSignedCertificate是我尝试使用的内部类

5 个答案:

答案 0 :(得分: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" });
    }
}

请注意,以这种方式违反访问修饰符需要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"});
    }
}

答案 1 :(得分:19)

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

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

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

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

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" });

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

答案 2 :(得分:3)

如果它是internal到不属于你的程序集并且构造函数标记为private,则程序集的作者正在努力阻止您创建该对象。

以下是非常邪恶的,因为你依赖的非公开课程和方法可能会在没有事先通知的情况下改变你。

  

已添加:System.ServiceModel.Channels.SelfSignedCertificate是我尝试使用的internal

不要这样做。眨眼之间,框架可能会在你身边发生变化,破坏你的代码和你所有的辛勤工作。

那就是说,你可以这样做:

MethodInfo method = Type.GetType(assemblyQualifiedName).GetMethod("Create");
ABC o = (ABC)method.Invoke(null, new[] { "test" });

这会调用static方法Create。另一种选择是

MethodInfo method = Type.GetType(assemblyQualifiedName).GetConstructor(
                        BindingFlags.NonPublic | BindingFlags.Instance,
                        null,
                        new[] { typeof(string) },
                        null
                    );
ABC o = (ABC)method.Invoke(new[] { "test" });

使用反射加载接受string作为参数的构造函数。

获取程序集限定名称的简便方法是

string name = typeof(somePublicType).Assembly.GetType("Namespace.ABC");

其中somePublicType是一种公共类型,与ABC在同一个程序集中。

答案 3 :(得分:0)

除非是嵌套类,否则不能使用私有构造函数实例化类。

http://msdn.microsoft.com/en-us/library/kcfb85a6%28VS.71%29.aspx

答案 4 :(得分:0)

使用Activator类实例化它

Activator.CreateInstance(myType, true);