解决从泛型类型参数派生的问题

时间:2012-10-31 17:19:22

标签: c# .net generics refactoring

我意识到不可能从泛型类型参数派生,并且我理解允许的所有复杂情况。

所以我的问题是,我该如何解决这个问题?我试图消除一些重复的代码和最好的解决方案(这不是一个解决方案,因为它无法完成)我想出了会做这样的事情:

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&amp; ReportExecution2005类派生自SoapHttpClientProtocol,派生自HttpWebClientProtocol。覆盖方法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覆盖的方式重构此代码)?

1 个答案:

答案 0 :(得分: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();
        ...
    }