【发布时间】:2021-02-12 10:23:30
【问题描述】:
我正在尝试编写一个流畅的 API 来在我的 C# 程序中构建实体。
我有一个基础实体,它具有一些属性和一组多态实体:它们都来自一个通用的基础类型,但有些会有额外的属性。
这是一个例子:
public interface IGarageBuilder
{
public IGarageBuilder Label(string label);
public IGarageBuilder AddCar(Action<ICarBuilder> configure);
public IGarageBuilder AddBike(Action<IBikeBuilder > configure);
}
public interface IVehicleBuilder
{
public IVehicleBuilder Model(string model); // <- That is the member that is causing me trouble
}
public interface IBikeBuilder : IVehicleBuilder
{
}
public interface ICarBuilder : IVehicleBuilder
{
public ICarBuiler HorsePoser(int horsePower);
}
(我写的软件有很多IVehicleBuilder共有的属性,我简化了很多)。
我遇到了 IVehicleBuilder 接口的问题:如上定义,以下代码将无法编译:
public void BuildGarage(IGarageBuilder builder)
{
builder.Label("My dream garage")
.AddCar(opt => opt.Model("Ford").HorsePower(120)); // <- this fails because .Model() returns a IVehicleBuilder interface, not an ICarBuilder
}
现在,我可以摆脱 IVehicleBuilder 和 ICarBuilder 之间的依赖关系,并将“Model()”API 复制到 ICarBuilder 和 IBikeBuilder,但在我的实际应用程序中,我有几十个这样的 API,其中几个被覆盖以允许配置实体的不同方式。此外,我还必须复制实现,因为它们现在返回不同的类型。
有没有办法避免所有代码重复?
【问题讨论】:
-
您可以将
IVehicleBuilder设为通用,这是一种选择吗? -
不应该
AddCar返回ICarBuilder的类型而不是IGarageBuilder? -
您正在制造汽车,但未指定您正在制造汽车,您需要一种方法来下拉到更具体的类型(即让
IVehicleBuilder返回汽车/自行车)或尽早从更具体的类型开始。 -
@Matin 不,AddCar 接受一个委托,该委托将构建器作为参数并返回 IGarageBuilder(因此可以添加新车辆)