从数据库读取创建正确的具体类型

Creating correct concrete type from database read

我正在从事的一个项目如果添加更多的抽象概念会受益匪浅,但我面临着一个我似乎无法克服的问题。

本质上我们有可以分配和消费的服务,但它们的消费率都有点不同。这种区别对于报告和安排这些服务的使用很重要。

我不太确定如何获取从数据库接收的数据并确保创建正确的具体类型。我是不是想得太多了,我可以做些更容易的事情吗?我唯一能想到的就是让 switch 语句根据指定的时间单位确定要创建的类型,但这看起来很草率。

UnitInterval(我欢迎将其重命名为看起来不那么混乱的名称)应该包含服务的消耗单位(1、15、30、60),然后 UnitSize 将是分钟、小时或天。 UnitSizes 保存在引用 table 中,并使用相应的天、分钟、小时文本进行 ID。所以在我的 table 分钟中有一个 ID = 1,小时 = 2,天 = 3,并且取决于是否需要调整这些间隔,它们可以在未来进行调整。

如何从数据库中获取UnitSize之类的东西并确保正确执行?我只是以完全错误的方式解决这个问题吗?

基本上我的最终目标是我将有另一个 class,其中仅包含 List<WorkableService>,我可以用它来生成包含正确单位、任何成本计算、持续时间等的报告。

public abstract class WorkableService
{
    public int UnitSizeId { get; set; }
    public string UnitSizeText { get; set; } 

    public double UnitInterval { get; set; }
    public abstract TimeSpan Duration { get; }
    public double UnitsAvailable { get; set; }
    public double Adjustment { get; set; }
    public decimal Rate { get; set; }
}

public class MinuteService : WorkableService
{
    public override TimeSpan Duration
    {
        get
        { 
            return TimeSpan.FromMinutes(UnitInterval); 
        }
    }
}

public class HourlyService : WorkableService
{
    public override TimeSpan Duration
    {
        get 
        {
            return TimeSpan.FromHours(UnitInterval);        
        }
    }
}

public class DailyService : WorkableService
{
    public override TimeSpan Duration
    {
        get 
        {
            return TimeSpan.FromDays(UnitInterval);
        }
    }
}

如果您在编译时确定您可能需要的所有选项,则 switch 方法是完全有效的。维基百科上的更多基本信息 factory pattern,但打开枚举值或字符串标识符是一般概念。

或者,查看 Activator.CreateInstance,您可以使用它根据您可能从数据库动态加载的类型名称创建新对象。在某些情况下,我们这样做是为了让我们无需重新编译基本服务即可添加新的支持类型。

你所说的草率的 switch 语句就是所谓的工厂模式。假设您的 WorkableService 基本构造函数采用 UnitInterval:

static class WorkableServiceFactory
{
    public static WorkableService Get(int unitSizeId, double unitInterval)
    {
        switch (unitSizeId)
        {
            case 1:
                return new MinuteService(unitInterval);
            case 2:
                return new HourlyService(unitInterval);
            case 3:
                return new DailyService(unitInterval);
            default:
                throw new ArgumentOutOfRangeException("unitSizeId");
        }
    }
}

我通常不是工厂的粉丝(出于某种原因,它们是书中每个 Java EE 笑话的屁股),但这实际上是一个有效的场景。