在C#中从类外部访问私有构造函数

如果我使用私有默认构造函数和具有参数的公共构造函数定义类,如何访问私有构造函数?

public class Bob { public String Surname { get; set; } private Bob() { } public Bob(string surname) { Surname = surname; } } 

我可以通过类上的静态方法访问私有构造函数,如下所示:

 public static Bob GetBob() { return new Bob(); } 

我认为我可以通过扩展方法访问私有构造函数,因为(根据我的理解)扩展方法被翻译,以便它们看起来是类上的静态方法,但我不能:

 static class Fred { public static Bob Bobby(this Bob bob) { return new Bob(); } } 

那么,我如何访问私有构造函数?

谢谢


编辑:

我想这样做的原因是我想为我们的某个业务类创建测试,但不允许此类的使用者能够错误地实例化对象。 我正在测试它,所以我知道(我希望!)在什么情况下测试会失败。 我现在还在测试n00b,所以我的想法可能是也可能不是做事的“错误方式”。

我已经改变了我的测试策略,就像这个类的消费者那样做事,即调用公共方法,如果公共方法没问题,假设私有方法没问题。 我仍然更愿意测试私人方法,但我的老板在可交付物上呼吸:-(

由于某种原因,默认构造函数是私有的。 开发人员不会为了娱乐而私密。

但是如果您仍然想使用默认构造函数,则可以使用reflection来获取它。

 var constructor = typeof(Bob).GetConstructor(BindingFlags.NonPublic|BindingFlags.Instance, null, new Type[0], null); var instance = (Bob)constructor.Invoke(null); 

编辑

我看到了你对测试的评论。 切勿测试受保护的或私有的方法/属性。 如果您无法通过公共API设法测试这些方法/属性,那么您可能做错了。 删除它们或重构该类。

编辑2

忘了绑定旗帜。

有几种方法可以解决这个问题:

:使构造函数公开。 如果你需要从类外部访问它,为什么它是私有的(可能你只想访问私有构造函数进行测试,在这种情况下这是一个有效的问题)。

:使构造函数受到保护,然后通过派生类访问它:

 public class Bob { public String Surname { get; set; } protected Bob() { } public Bob(string surname) { Surname = surname; } } public class Fred : Bob { public Fred() : base() { } } 

:使用reflection(如jgauffin所示)。

除了@ jgauffin的回答,它告诉我们如何通过reflection调用私有构造函数:

是否可以更改私有构造函数的修饰符?

您似乎正在代码中实现Factory Pattern。 因此,修饰语应该是internal

 public class Product { //others can't create instances directly outside the assembly internal Product() { } } public class ProductProvider { //they can only get standardized products by the provider //while you have full control to Product class inside ProductProvider public static Product CreateProduct() { Product p = new Product(); //standardize the product return p; } } 

扩展方法

 public static MyExt { public static void DoSomething(this Product p) { } } 

调用p.DoSomething()实际上等于MyExt.DoSomething(p) 。 它不是将此方法放入类Product中。

您可以通过reflection实例化该类型的实例。

Bobby的方法仍然在另一个类中,称为Fred。 这就是为什么你不能访问Bob类的prive构造函数。 附加方法无法实现您的目标。 即使它们可以附加在另一个类上,它们仍然在该类之外声明并遵循通常的范围/访问规则。

如果您正在使用dotnet核心,您可以执行以下操作,甚至无需进行任何reflection:

 YourCustomObject player = (YourCustomObject)Activator.CreateInstance(typeof(YourCustomObject),true); 
 public class demo { private demo() { Console.WriteLine("This is no parameter private constructor"); } public demo(int a) { demo d = new demo('c');// u can call both private contstructors from here demo dd = new demo(); Console.WriteLine("This is one parameter public constructor"); } private demo(char a) { Console.WriteLine("This is one parameter public constructor::" + a); } } class Program { static void Main(string[] args) { demo obj = new demo(7); // demo obj = new demo(); // it will raise error Console.ReadLine(); } }