0

只是好奇是否有解决方案而不使基类方法虚拟并且派生方法标记为覆盖:

我希望它跳转到派生方法中,将属性设置为 true(出于测试目的,几乎就像这是一个模拟),但它正在跳转到基类中。唯一的解决方案是使基础虚拟化,我想我可以在派生中将其标记为新的,这样就可以了。

   public class SomeClass
   {
      private readonly IFoo _foo;

      public SomeClass(IFoo foo)
      {
         _foo = foo;
      }

      public void DoSomething()
      {
         _foo.DoFoo();
      }
   }

   public interface IFoo
   {
      void DoFoo();
   }

   public class Foo : IFoo
   {
      public void DoFoo()
      {

      }
   }

   public class Foo2 : Foo
   {
      public bool DoFooWasCalled { get; set; }

      public new void DoFoo()
      {
         DoFooWasCalled = true;
         base.DoFoo();
      }
   }

这是失败的测试:

   [TestFixture]
   public class TestingCSInheritance
   {
      [Test]
      public void TestMethod()
      {
         var foo = new Foo2();
         var someClass = new SomeClass(foo);
         someClass.DoSomething();
         foo.DoFooWasCalled.ShouldBe(true);
      }
   }

我的猜测是,因为我正在使用带有接口的依赖注入,所以它使用的是基类,但我不确定为什么。

4

2 回答 2

4

唯一的解决方案是使基础虚拟化,我想我可以在派生中将其标记为新的,这样就可以了。

不会。如果您创建一个新方法,只有知道编译时类型为的表达式的代码Foo2才会调用Foo2.DoSomething.

即使TestMethod知道fooas a Foo2SomeClass.DoSomething也只知道 as IFoo,所以它只是使用IFoo实现。Foo2.DoSomething不是. _ _IFoo

您需要多态性,但您已经通过不使用虚拟方法有效地丢弃了它。

唯一的其他选择是在 Foo2 中重新实现 IFoo,这是 Sergey 描述的解决方案。请注意,这最终会产生一些非常混乱的代码。任何类型的方法隐藏几乎总是如此。从根本上说,如果你想要虚拟方法的效果,你应该使用虚拟方法......

或者,如果您使用组合而不是继承,它会更干净:

public class MockFoo : IFoo
{
    private readonly Foo foo = new Foo();
    private bool doSomethingWasCalled;

    public void DoSomething()
    {
        doSomethingWasCalled = true;
        foo.DoSomething();
    }
}

这将调用委托DoSomething而不是尝试处理继承层次结构。

于 2012-07-22T19:37:11.693 回答
1

尝试像这样更改您的Foo2声明:

public class Foo2 : Foo, IFoo
于 2012-07-22T19:33:00.540 回答