在C#

问题描述 投票:0回答:6

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

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(); } } ,我该如何访问私人构造函数? 谢谢你

Edit:

我想这样做的原因是我想为我们的一个商务类创建测试,但不允许该课程的消费者能够错误地实例化对象。我正在测试它,所以我知道(我希望!)测试将失败。我现在仍在测试N00B,所以我的想法可能是做事的“错误方式”。 我已经改变了我的测试策略,以按照本班的消费者的方式做事,即调用公共方法,如果可以的话,则假设私人方法还可以。我仍然宁愿测试私人方法,但是我的老板

iis

在可交付的脖子上呼吸着我的脖子:-(


新答案(九年后)

现在有几个activator.createinstance的过载,可让您使用非公共构造函数:

Activator.CreateInstance(typeof(YourClass), true);

c# constructor visibility default-constructor
6个回答
60
投票
=使用非公共构造函数。

.

回答

默认构造函数是私人的,这是有原因的。开发人员不会让它变得私密。

但是,如果您仍然想使用默认构造函数,则使用反射。

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

eDit

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

Edit2 将绑定标志固定。

有关此问题的几种方式:

ONE

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

:对构造函数进行保护,然后通过派生类访问它:

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

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

除 @jgauffin的答案外,还告诉如何通过反射调用私人构造师:


2
投票
似乎您正在代码中实现工厂模式。因此,修饰符应该为

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)。它不是将此方法放入类产品中。


2
投票

如果您使用的是dotnet核心,则可以执行以下操作,而无需进行任何反思:

YourCustomObject player = (YourCustomObject)Activator.CreateInstance(typeof(YourCustomObject),true); 激活器仅在系统名称空间中。

如果类只有私人且没有公共构造函数,则只能在此类中的嵌套类中访问。值得一提的是,无法得出具有私人默认构造函数的类。
因此,只有将构造函数或构造函数声明为私人(在没有公共讲师的课堂中)是有意义的,当时该类别的实例仅在此类中的嵌套类中创建。没有其他有效的位置来实施此类班级。
    

这个线程对我来说是很满意的。
否,对我自己的更好解决方案是

var myInstance = Activator.CreateInstance<MyInstance>();

批准和更新的答案效果很好,但是线路blloow
Activator.CreateInstance(typeof(YourClass), true);

返回一个对象,然后需要以特定类型进行转换。等等:
var yourType =  Activator.CreateInstance(typeof(YourClass), true);
YourClass yourType2 = (YourClass)(yourType );


1
投票
线波纹管,是me的一个better解决方案

var myInstance = Activator.CreateInstance<MyInstance>();
    

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


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


0
投票
方法Bobby仍处于另一个名为Fred的类别中。这就是为什么您无法访问Bob类的Prive构造函数的原因。您要尝试使用的方法是不可能的。即使可以将它们附加在另一个类上,他们仍然在该类外宣布并遵循通常的范围/访问规则。

最新问题
© www.soinside.com 2019 - 2025. All rights reserved.