如何在c#中调用受保护的构造函数?

Arn*_*psa 15 c# inheritance constructor

如何调用受保护的构造函数?

public class Foo{
  public Foo(a lot of arguments){}
  protected Foo(){}
}
var foo=???
Run Code Online (Sandbox Code Playgroud)

这显然未通过测试:

public class FooMock:Foo{}
var foo=new FooMock();
Assert(typeof(Foo), foo.GetType());
Run Code Online (Sandbox Code Playgroud)

Ser*_*-Tm 28

调用无参数保护/私有构造函数:

Foo foo = (Foo)Activator.CreateInstance(typeof(Foo), true);
Run Code Online (Sandbox Code Playgroud)

使用参数调用非公共构造函数:

  var foo = (Foo)typeof(Foo)
    .GetConstructor(
      BindingFlags.NonPublic | BindingFlags.CreateInstance | BindingFlags.Instance, 
      null, 
      new[] { typeof(double) }, 
      null
    )
    .Invoke(new object[] { 1.0 });

  class Foo
  {
     private Foo(double x){...}
  }
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 24

基本上,你只能从子类中调用它.你的FooMock类已经调用了受保护的构造函数,因为它等同于:

public class FooMock : Foo
{
    public FooMock() : base() // Call the protected base constructor
    {
    }
}
Run Code Online (Sandbox Code Playgroud)

然而,你的断言将失败,因为对象的类型提及的是fooFooMock,没有Foo.

表单的断言foo is Foo 通过.

您不能通过Foo直接调用受保护的构造函数来构造实例.它被保护而不是公共的点是确保它只被子类调用(或者在Foo它自己的文本中).

您可以在完全信任环境中使用反射调用它,但我敦促您不要这样做.

  • @Arnis:您可能需要考虑使用`protected internal`然后使用`InternalsVisibleTo`来允许测试程序集访问生产程序集的内部. (6认同)
  • @Arnis L.:那时你做的不仅仅是提出一个黑客来进行测试通过,这与完全没有编写测试一样有用.这是退一步看看_Why_这个构造函数是`protected`的好时机,因为它暗示你寻求(并且正在测试)的行为明显不受支持(因此,不可测试). (2认同)
  • @Arnis:通常如果您需要通过反射绕过辅助功能模型,这表明您不应该尝试访问相关成员 - 或者您应该自己增加可访问性. (2认同)