泛型,工厂和返回更多衍生类型

时间:2017-08-01 15:05:48

标签: c# inheritance decorator factory-pattern

我正在玩一种工厂,装饰和责任链的混搭。基本上,我正在建立一个接收请求对象的工厂,对其进行分析,并将其进一步传递到更具体的内部工厂。我已到达下面的结构,但它有问题。

public abstract class AbstractFactoryRequest { }

public class SpecificFactoryRequest : AbstractFactoryRequest { }

public class MoreSpecificFactoryRequest : SpecificFactoryRequest { }

public interface IThing { }

public interface IThingFactory<in T> where T : AbstractFactoryRequest
{
    IThing GetThing(T request);
}

public abstract class AbstractThingFactory<T> : IThingFactory<T> where T : AbstractFactoryRequest
{
    public IThing GetThing(T request)
    {
        var innerFactory = GetInnerFactory(request);

        return innerFactory.GetThing(request);
    }

    protected abstract IThingFactory<T> GetInnerFactory(T request);
}

public class SpecificThingFactory : AbstractThingFactory<SpecificFactoryRequest>
{
    protected override IThingFactory<SpecificFactoryRequest> GetInnerFactory(SpecificFactoryRequest request)
    {
        return (IThingFactory<SpecificFactoryRequest>)new MoreSpecificThingFactory();
    }
}

public class MoreSpecificThingFactory : AbstractThingFactory<MoreSpecificFactoryRequest>
{
    protected override IThingFactory<MoreSpecificFactoryRequest> GetInnerFactory(MoreSpecificFactoryRequest request)
    {
        // return an even more specific factory...
    }
}

尝试从MoreSpecificThingFactory内返回新SpecificThingFactory时出现问题。如上所述,ReSharper将其称为可疑演员,如果没有演员表,编译器会说在MoreSpecificThingFactory和IThingFactory之间没有隐式转换。我原以为这可能会有效,因为继承就在那里。有办法解决这个问题吗?

1 个答案:

答案 0 :(得分:1)

您收到此错误是因为您将参数声明为contravariant,这意味着您只能将其用作一种方法参数,而不能用作接口方法的返回类型。以下是an article关于泛型类型的差异。

现在想想你正在尝试做什么。如果你转换为不太具体的类型,这意味着你可以将较少的特定参数传递给只接受更具体参数的方法,你显然不能这样做。

要进行此演员表,您应该按如下方式定义MoreSpecificThingFactory:

public class MoreSpecificThingFactory : AbstractThingFactory<SpecificFactoryRequest>
{
    protected override IThingFactory<SpecificFactoryRequest> GetInnerFactory(SpecificFactoryRequestrequest)
    {
        if (request is MoreSpecificFactoryRequest)
        {
            // return an even more specific factory...
        }
        // throw an exception or do something else
    }
}

修改

您似乎需要在此处应用chain of responsibility模式