新关键字不强制隐藏 - OOP C#

时间:2015-02-18 08:53:46

标签: c# oop inheritance dependency-injection

我有以下情况:

我想模拟一个界面,以便我可以对我的应用进行单元测试。我试图不创建一个实现我的接口的新mock类,但创建一个继承原始具体类的新类,并在调用该方法时使用new关键字强制新行为。但由于某种原因,正在调用具体类的方法,而不是我创建的类(作为模拟)

以下代码:

public interface IMyService 
{ 
    Model GetModelData(int id)
}

public class MyService : IMyService
{
    public Model GetModelData(int id)
    { 
       //call to db     
    }
}

public class MyService2 : MyService
{
    public MyService2()
        : base(new MyRepository())
    {    
    }

    public new Model GetModelData(int id)
    { 
        return new Model();
    }
}

注入依赖:

x.ForRequestedType<IMyService>().TheDefaultIsConcreteType<MyService2>();

检索具体类:在调试时我可以看到myService指向MyService2类,但该方法在MyService类上执行。

_myServie = ObjectFactory.GetInstance<IMyService>();
                Model modelData = _myServie.GetModelData(5);

2 个答案:

答案 0 :(得分:3)

只需使用new即可创建新方法,而无需将其与界面相关联。您正在使用真实代码中的接口(我假设),因此您希望将接口方法绑定到新方法。为此,您必须声明您再次实施界面。以下是显示差异的示例:

using System;

interface IFoo
{
    void Bar();
}

class Normal : IFoo
{
    public void Bar()
    {
        Console.WriteLine("Normal.Bar");
    }
}

class Extended1 : Normal
{
    public new void Bar()
    {
        Console.WriteLine("Extended1.Bar");
    }
}

class Extended2 : Normal, IFoo
{
    public new void Bar()
    {
        Console.WriteLine("Extended2.Bar");
    }
}

class Test
{
    static void Main()
    {
        IFoo x = new Extended1();
        IFoo y = new Extended2();

        x.Bar();
        y.Bar();
    }
}

输出:

Normal.Bar
Extended2.Bar

因此,如果您将类声明更改为:

public class MyService2 : MyService, IMyService

你应该发现它只是有效。我不能说我是这种方法的忠实粉丝,请注意 - 调用方法的MyService内的任何内容都会调用自己的实现,除非它恰好通过调用IMyService - 类型参考。你可以在你的具体类虚拟中实现接口实现,而在你的子类中覆盖它;在某些方面会更好,但在其他方面会更糟。基本上,这种半继承&#34;对我来说感觉很脆弱。

我怀疑如果你有一个抽象的基类,你的真实实现和你的测试实现都来自......

答案 1 :(得分:1)

我认为您正在寻找的是将MyService上的方法设为虚拟并在MyService2中覆盖它。像这样:

public interface IMyService 
{ 
    Model GetModelData(int id)
}

public class MyService : IMyService
{
    public virtual Model GetModelData(int id)
    { 
       //call to db     
    }
}

public class MyService2 : MyService
{
    public MyService2()
        : base(new MyRepository())
    {    
    }

    public override Model GetModelData(int id)
    { 
        return new Model();
    }
}

这样,如果在子类中重写该方法,则将调用子类方法,否则基类将使用方法调用。