【问题标题】:How to pass the base class on the caller side and accept derived如何在调用方传递基类并接受派生
【发布时间】:2020-04-30 14:13:53
【问题描述】:

我有一个返回基类响应的服务。它肯定有派生响应。

    public class ResponseBase
    {
        public string Response { get; set; }
    }

    public class DerivedResponse : ResponseBase
    {
        public string AdditionalResponse { get; set; }
    }

这里是服务代码:

public class SomeService
{
    public ResponseBase GetResponse() => new DerivedResponse();
}

然后我需要以不同的方式处理不同的响应。显然尝试通过 100500 if\elses 获得适当的行为不是一个好的解决方案。我决定为每个具体的响应设置一个特殊的响应处理程序。

    public interface IHandlerBase<T>
        where T : ResponseBase
    {
        void Handle(T response);
    }

    public class DerivedResponseHandler : IHandlerBase<DerivedResponse>
    {
        public void Handle(DerivedResponse response)
        {

        }
    }

此外,我们需要封装行为,这些行为将决定获取什么处理程序以处理具体响应,我认为工厂是一个不错的解决方案。我遇到了一个问题,因为我不知道要返回什么,因为我不知道编译时派生类型:

    public class HandlerFactory {
        public IHandlerBase<> /*WHAT RETURN HERE*/ CreateHandler(ResponseBase response)
        {
            //decide the derived type of the 'response' and return appropriate handler
        }
    }

当然,我们可以删除泛型参数,在所有处理程序中接受基类,然后在具体处理程序中转换为特殊的,但我认为这不是一个好的解决方案。那么您能否建议如何以一种干净的方式做到这一点,也许是一些模式或解决方案?

【问题讨论】:

  • 我看到两个选项,你可以给GetResponse 一个通用参数,比如T GetResponse&lt;T&gt;() where T : ResponseBase,或者你可以给CreateHandler 一个通用参数,比如IHandlerBase&lt;T&gt; CreateHandler&lt;T&gt;(T response)
  • @Ackdari,我不能 1)GetResponse 不能返回泛型 ,因为它也是由内部方法确定的,而不是由调用方确定 2)CreateHandler 也不能是泛型的,因为我我打电话给工厂时不知道实际的派生类型。所以工厂应该也可以在内部确定它

标签: c# design-patterns architecture factory-pattern


【解决方案1】:

我们可以通过创建新的 NotGeneric interface 来做到这一点:

    public interface IHandlerBase
    {
        void Handle(ResponseBase response);
    }

    public interface IHandlerBase<T> : IHandlerBase
        where T : ResponseBase
    {
        void Handle(T response);
    }

    public class DerivedResponseHandler : IHandlerBase<DerivedResponse>
    {
        public void Handle(DerivedResponse response)
        {

        }

        public void Handle(ResponseBase response)
        {
            var actualParameter = (DerivedResponse) response;
            Handle(actualParameter);
        }
    }

在这种情况下,派生处理程序中有两种方法:一种用于实际处理,另一种用于适应(类似于适配器模式)。问题是没关系,也许有人有更好的解决方案。

【讨论】:

    猜你喜欢
    • 2018-10-24
    • 2013-04-11
    • 1970-01-01
    • 2014-09-05
    • 2016-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-23
    • 2014-01-27
    相关资源
    最近更新 更多