如何在C#中使用私有构造函数实例化对象?

时间:2009-04-02 09:20:30

标签: c# constructor instantiation private-constructor

我绝对记得在某个地方看到过使用反射或其他东西这样做的例子。这与用户无法创建的SqlParameterCollection有关(如果我没弄错的话)。不幸的是再也找不到了。

有人可以在这里分享这个技巧吗?并不是说我认为它是一种有效的开发方法,我只是对这样做的可能性非常感兴趣。

5 个答案:

答案 0 :(得分:57)

您可以使用 Activator.CreateInstance 的重载之一来执行此操作:Activator.CreateInstance(Type type, bool nonPublic)

使用true作为nonPublic参数。因为true匹配公共或非公共默认构造函数;和false仅匹配公共默认构造函数。

例如:

    class Program
    {
        public static void Main(string[] args)
        {
            Type type=typeof(Foo);
            Foo f=(Foo)Activator.CreateInstance(type,true);
        }       
    }

    class Foo
    {
        private Foo()
        {
        }
    }

答案 1 :(得分:40)

// the types of the constructor parameters, in order
// use an empty Type[] array if the constructor takes no parameters
Type[] paramTypes = new Type[] { typeof(string), typeof(int) };

// the values of the constructor parameters, in order
// use an empty object[] array if the constructor takes no parameters
object[] paramValues = new object[] { "test", 42 };

TheTypeYouWantToInstantiate instance =
    Construct<TheTypeYouWantToInstantiate>(paramTypes, paramValues);

// ...

public static T Construct<T>(Type[] paramTypes, object[] paramValues)
{
    Type t = typeof(T);

    ConstructorInfo ci = t.GetConstructor(
        BindingFlags.Instance | BindingFlags.NonPublic,
        null, paramTypes, null);

    return (T)ci.Invoke(paramValues);
}

答案 2 :(得分:4)

答案 3 :(得分:2)

如果这个类不是你的类,那么听起来就像故意编写API来防止这种情况,这意味着你的方法可能不是API编写者的意图。看看文档,看看是否有推荐的方法来使用这个类。

如果您可以控制该类并希望实现此模式,那么它通常通过类上的静态方法实现。这也构成了Singleton模式的关键概念。

例如:

public PrivateCtorClass
{
    private PrivateCtorClass()
    {
    }

    public static PrivateCtorClass Create()
    {
        return new PrivateCtorClass();
    }
}

public SomeOtherClass
{
    public void SomeMethod()
    {
        var privateCtorClass = PrivateCtorClass.Create();
    }
}

SqlCommandParameter是一个很好的例子。他们希望您通过调用以下内容来创建参数:

var command = IDbConnnection.CreateCommand(...);
command.Parameters.Add(command.CreateParameter(...));

我的例子不是很好的代码,因为它没有演示设置命令参数属性或重用参数/命令,但你明白了。

答案 4 :(得分:1)

如果您Typeprivateinternal

也会有所帮助:

 public static object CreatePrivateClassInstance(string typeName, object[] parameters)
    {
        Type type = AppDomain.CurrentDomain.GetAssemblies().
                 SelectMany(assembly => assembly.GetTypes()).FirstOrDefault(t => t.Name == typeName);
        return type.GetConstructors()[0].Invoke(parameters);
    }