2012-10-31 45 views
1

我意識到不可能從泛型類型參數中派生出來,並且我理解如果允許出現的所有複雜問題。解決從泛型類型參數派生

所以我的問題是,我該如何解決此問題?我想消除一些重複的代碼和最佳解決方案(這不是一個解決方案,因爲它不能做)我想出了將做這樣的事情:

public class Proxy<T> : T where T : CommonBaseClass 

我之所以會想這樣做是否覆蓋CommonBaseClass中的某些方法。

這裏是我的項目的一些實際的代碼示例:

public class ReportingServiceProxy : ReportingService2010 
{ 
    protected override WebResponse GetWebResponse (WebRequest request) 
    { 
     WebResponse response = base.GetWebResponse(request); 
     // Do override stuff here 
     return response; 
    } 
} 

public class ReportingExecutionProxy : ReportExecution2005 
{ 
    protected override WebResponse GetWebResponse (WebRequest request) 
    { 
     WebResponse response = base.GetWebResponse(request); 
     // Do override stuff here 
     return response; 
    } 
} 

ReportingService2010 & ReportExecution2005類從SoapHttpClientProtocolHttpWebClientProtocol派生既得到上面的例子。替代方法GetWebResponseGetWebRequest都覆蓋HttpWebClientProtocol中的方法並且是相同的。這些方法是代碼重複存在的地方,我試圖重構。

爲了完整起見,這裏是一些額外的代碼,我執行上面的代碼:

public abstract class SSRSReportBase<T> where T : new() 
{   
    protected T ssrs; 
    protected abstract void ServiceLogon(); 

    public SSRSReportBase() 
    { 
     ServiceLogon(); 
     // Do other common constructor work here. 
    } 
} 

// Implementation #1 
public class SSRSReportExecution : SSRSReportBase<ReportExecutionProxy> 
{ 
    protected override void ServiceLogon() 
    { 
     ssrs.LogonUser("LoginName", null, null); 
    } 

    // Create additional wrapper methods for ReportExecution2005 
} 

// Implementation #2 
public class SSRSReportingService : SSRSReportBase<ReportingServiceProxy> 
{ 
    protected override void ServiceLogon() 
    { 
     ssrs.LogonUser("LoginName", null, null); 
    } 

    // Create additional wrapper methods for ReportingService2010 
} 

我想出的唯一辦法是不是一個可行的解決方案,所以很明顯它不是一個解決方案。這裏是代碼:

public class ReportProxy<T> : T where T : HttpWebClientProtocol, new() 
{ 
    protected override WebResponse GetWebResponse (WebRequest request) 
    { 
     WebResponse response = base.GetWebResponse(request); 
     return response; 
    } 
} 

// Implementation #1 
public class SSRSReportExecution : SSRSReportBase<ReportProxy<ReportExecution2005>> 
{ 
} 

// Implementation #2 
public class SSRSReportingService : SSRSReportBase<ReportProxy<ReportingService2010>> 
{ 
} 

問:所以我的問題是,如何可以在這個代碼以這樣的方式重構,以消除重複的代碼(GetWebRequestGetWebResponse覆蓋)?

+0

所以,你想有效地圍繞類(X,Y)的包裝,所以你可以調用一個方法,並獲得X和Y同樣的效果?也許我對你想要的東西感到困惑。 – Tejs

+0

您可以考慮組合而不是繼承來實現您想要做的事情嗎?所以你將有一個T的私人實例,將獲得對GetWebResponse的調用? – nieve

+0

我在想這將是最佳解決方案。拿一個內部的'T'引用,這樣你就可以通過方法將它的操作暴露給底層的'T'實現。 – Tejs

回答

1

解決方案是根本不使用泛型並使用工廠模式。而不是具有BaseClassnew()約束的通用參數。鍵入所有內容BaseClass併爲new()提供工廠。這可以是完整的工廠類或輕量級工廠代表。

public interface IProtocolFactory 
{ 
    ProtocolBaseClass Create(); 
} 

public class SomeDerivedProtocolFactory : IProtocolFactory 
{ 
    public ProtocolBaseClass Create() 
    { 
     return new SomeDerivedProtocol(); 
    } 
} 

您甚至可能在工廠中添加額外的初始化代碼。

public class ReportProxy 
{ 
    private IProtocolFactory _factory; 

    public ReportProxy(IProtocolFactory factory) 
    { 
     _factory = factory; 
    } 

    public void DoSomething() 
    { 
     ProtocolBaseClass protocol = _factory.Create(); 
     ... 
    } 
} 

使用委託

private Func<ProtocolBaseClass> _createProtocol; 

    public ReportProxy(Func<ProtocolBaseClass> createProtocol) 
    { 
     _createProtocol= createProtocol; 
    } 

    public void DoSomething() 
    { 
     ProtocolBaseClass protocol = _createProtocol(); 
     ... 
    } 
+0

謝謝 - 這幾乎是我所做的。我最終放棄了泛型,並將工廠模式與接口和服務的部分類一起使用來描述常見行爲(覆蓋)。因此,解決方案:使用部分類和接口,而不是泛型。 – Steve