从接口或类返回调用子实例

时间:2017-06-19 12:13:35

标签: c# .net inheritance design-patterns

所以这个问题是一个明确的案例,一石二杀(一个设计和代码问题)我有一个基类,它有一个基本接口

interface IBase
{
   IBase Method1();
}

abstract class Base : IBase
{
   IBase Method1()
   {
     //do work
     return this;
   }
}

现在是子类

interface IChild1 : IBase
{
  IChild1 ChildMethod();
}

class Child1 : Base, IChild1
{
  public IChild1 ChildMethod()
  {
    //do work 
    // this would work fine Method1(); ChildMethod2();
    //but I want to chain methods
    Method1().ChildMethod2();
    return this;
  }

  void ChildMethod2()
  {
    //do work
  }
}

问题的关键是我希望基类返回子类实例。从ChildMethod()方法中的代码可以看出,基类方法Method1()返回IBase的实例,因此无法链接ChildMethod2()。是的,我可以在不必链接方法的情况下生活,但我们假设这是我唯一的选择。

这是我尝试使用泛型

interface IBase<T> where T : IBase<T>
{
    T Method1();
}

abstract class Base<T> : IBase<T> where T : Base<T>
{
    public T Method1()
    {
        //do work
        return (T)this;
    }
}

interface IChild1 : IBase<IChild1>
{
    IChild1 ChildMethod();
}

class Child1 : Base<Child1>, IChild1
{
    public IChild1 ChildMethod()
    {
        //do work
        Method1(); ChildMethod2();
        return this;
    }

    void ChildMethod2()
    {
        //do work
    }        
}

为了清楚地说明我想要实现的是对于我对基类的每次调用(在这种情况下为接口)我希望返回调用类/接口。 注意:使用Autofac进行依赖项注入

1 个答案:

答案 0 :(得分:0)

我认为你可以在保留接口和基类的同时这样做:

interface IBase<TSelf> where TSelf : IBase<TSelf> {
    TSelf Method1();
}

interface IChild1 : IBase<IChild1> {
    IChild1 ChildMethod();
    void ChildMethod2();
}

class Base<TSelf> : IBase<TSelf> where TSelf : IBase<TSelf> {
    public TSelf Method1() {
        //do work
        // need to double-cast here or just do            
        return (TSelf) (IBase<TSelf>) this;
    }
}

class Child1 : Base<IChild1>, IChild1 {
    public IChild1 ChildMethod() {
        //do work
        Method1().ChildMethod2();
        return this;
    }

    public void ChildMethod2() {
        //do work
    }
}

但正如您在评论中指出的那样,这不会与继承树中的更多成员一起工作。如果你可以删除接口,你可以这样做:

public abstract class Base<TSelf> where TSelf : Base<TSelf> {
    public TSelf Method1() {
        //do work
        // need to double-cast here or just do            
        return (TSelf) this;
    }
}

internal class Child1Impl<TSelf> : Base<TSelf> where TSelf : Child1Impl<TSelf> {
    public TSelf ChildMethod() {
        //do work
        Method1().ChildMethod2();
        return (TSelf) this;
    }

    public void ChildMethod2() {
        //do work
    }
}
// create subclass for ease of use, so that caller should not do Child1Impl<Child1> every time
class Child1 : Child1Impl<Child1> {

}

class SubChild1Impl<TSelf> : Child1Impl<TSelf> where TSelf : SubChild1Impl<TSelf> {
    public TSelf SubChildMethod() {
        Method1().ChildMethod();
        return (TSelf) this;
    }
}

class SubChild1 : SubChild1Impl<SubChild1> {

}

然后你可以这样做:

var test = new SubChild1();
test.Method1().ChildMethod().SubChildMethod();

也许你可以以某种方式对接口做同样的事情,但代码已经相当复杂,接口会更复杂(你已经有了基类,所以也许你真的不需要那些接口)。 / p>