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

时间:2010-11-12 08:26:18

标签: c# constructor visibility default-constructor

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

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,所以我的想法可能是也可能不是做事的“错误方式”。

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

8 个答案:

答案 0 :(得分:43)

默认构造函数是私有的。开发人员不会将其设为私密的。

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

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

修改

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

修改2

忘记绑定旗帜。

答案 1 :(得分:2)

有几种解决此问题的方法:

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

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

public class Bob
{
    public String Surname { get; set; }

    protected Bob()
    { }

    public Bob(string surname)
    {
        Surname = surname;
    }
}

public class Fred : Bob
{
    public Fred()
        : base()
    {
    }
}

:使用反射(如jgauffin所示)。

答案 2 :(得分:2)

除了@ jgauffin的答案之外,该答案讲述了如何通过反射调用私有构造函数:

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

您似乎正在代码中实现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)。它不是将这种方法放入类产品中。

答案 3 :(得分:0)

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

答案 4 :(得分:0)

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

答案 5 :(得分:0)

如果您正在使用dotnet核心,您可以执行以下操作,甚至不必反复思考:

YourCustomObject player = (YourCustomObject)Activator.CreateInstance(typeof(YourCustomObject),true);

答案 6 :(得分:0)

如果一个类只有私有且没有公共构造函数,则只能从该类中的嵌套类访问它。值得考虑的是,不能派生具有私有默认构造函数的类。 因此,仅当在类的嵌套类中创建类的实例时,才将一个或多个构造函数声明为私有(在没有公共讲师的类中)才有意义。没有其他有效的地方可以实例化此类。

答案 7 :(得分:-1)

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