仿制药,工厂和返回更多派生类型
问题描述:
我正在玩一种工厂,装饰者和责任链的混杂。实质上,我建立了一个接收请求对象的工厂,对其进行分析并将其传递给更具体的内部工厂。我已经到达了下面的结构,但它有问题。仿制药,工厂和返回更多派生类型
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
内归还new'd时出现。如上所述,ReSharper称这是一个可疑的演员阵容,如果没有演员阵容,编译器会说在MoreSpecificThingFactory和IThingFactory之间没有隐式转换。我曾想过,也许这会工作,因为遗产在那里。有没有办法来解决这个问题?
答
由于您将参数声明为逆变形,这意味着您只能用作方法参数的类型,而不能用作接口方法的返回类型,因此会出现此错误。这里是关于泛型类型差异的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模式
谢谢。我认为这是我正在寻找的。我会稍后处理它,并在当时选择答案。另外,我想提一提,我正在考虑“责任链”,并出于某种原因输入了“指挥链”。我会解决这个问题。 – bubbleking