2017-06-19 38 views
1

調用子實例所以這個問題是一個石頭的一個明顯例子二鳥(設計和代碼的問題),我有其中有一個基本接口返回從接口或

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依賴注入

+0

您的泛型示例不起作用嗎?我就是這麼做的。你應該能夠鏈接'Method1()。ChildMethod2();'。 –

+0

@ChrisPickford不起作用 – Ifetayo

+0

你真的需要將接口和父類一起使用嗎?如果你只有沒有接口的繼承鏈,那將很容易。在這種情況下泛型對接口來說也是無用的,因爲在使用它們時總是需要指定一些類:'IBase '。 – Evk

回答

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(); 

也許你能以某種方式做接口相同,但代碼已經相當複雜,會接口更加複雜(並且你已經有了基類,所以也許你並不需要這些接口)。

+0

謝謝Evk,但是如果我想要有Child1的子類和該子類的話,看起來如何。 – Ifetayo

+0

子類Child1會給類Child2:Child1 ,IChild2 ...因此class Child1 :Base >,IChild1其中T:Child1 Ifetayo

+0

是的,對於更多的類,您仍然可以這樣做,但代碼會變得太難以考慮。也許這表明你應該以某種方式重新考慮你的設計。 – Evk