代码之家  ›  专栏  ›  技术社区  ›  User

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

  •  27
  • User  · 技术社区  · 17 年前

    我肯定记得在某处看到过这样一个例子,使用反射或其他方法。这是与我有关的事情 SqlParameterCollection

    有人能在这里分享这个技巧吗?并不是我认为这是一种有效的发展方式,我只是对这样做的可能性很感兴趣。

    5 回复  |  直到 7 年前
        1
  •  75
  •   Mariano Desanze    10 年前

    您可以使用的重载之一 Activator.CreateInstance 为此: Activator.CreateInstance(Type type, bool nonPublic)

    使用 true 对于 nonPublic 论点因为 符合事实的 匹配公共或非公共默认构造函数;和 false 仅匹配公共默认构造函数。

    例如:

        class Program
        {
            public static void Main(string[] args)
            {
                Type type=typeof(Foo);
                Foo f=(Foo)Activator.CreateInstance(type,true);
            }       
        }
    
        class Foo
        {
            private Foo()
            {
            }
        }
    
        2
  •  52
  •   LukeH    17 年前
    // 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);
    }
    
        3
  •  1
  •   Neil Barnwell    17 年前

    如果该类不是您的类,那么听起来API是故意编写的,以防止出现这种情况,这意味着您的方法可能不是API编写者想要的。看看文档,看看是否有推荐的方法来使用这个类。

    如果你 控制类并希望实现此模式,那么它通常通过类上的静态方法实现。这也是构成单例模式的一个关键概念。

    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
  •   Mr.B    10 年前

    如果您的 Type private internal :

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