2

我有一个模型类:

public class Service
{

    public int ID { get; set; }

    public string description { get; set; }

    public decimal price { get; set; }
    public decimal cost { get; set; }
    public decimal manDay { get; set; }
    public decimal FTE{ get; set; }

}

我还有一个简单的控制器,它将遍历整个数据库表,并根据输入参数Services返回一个属性之一的 JSON 表:Service

public JsonResult _columns(int attributeCode)
{
    IQueryable<Service> services = db.Services.AsQueryable();

    MyJSONContainer jcontainer = new MyJSONContainer();

    switch(attributeCode)
    {
        case 0: 
            foreach(Service s in services) 
                jcontainer.addEntry(s.description, s.price);
            return Json(jcontainer);
        case 1: 
            foreach(Service s in services) 
                jcontainer.addEntry(s.description, s.cost);
            return Json(jcontainer);
        case 2: 
            foreach(Service s in services) 
                jcontainer.addEntry(s.description, s.manDay);
            return Json(jcontainer);
        default:
            foreach(Service s in services) 
                jcontainer.addEntry(s.description, s.FTE);
            return Json(jcontainer);   
    }
}

现在这段代码运行良好,但不是很干,特别是因为我将来可能会在foreach循环中增加更多的复杂性。

我很想知道在 DRY 设计模式方面拥有更多专业知识的人将如何编写这个函数。

谢谢

4

2 回答 2

2

您可以在您的类中添加一个方法(或者作为辅助类中的扩展方法,如果您不想在模型类中使用“attributeCode”逻辑,只需稍作更改)

public decimal GetValueFor(int attributeCode) {
  switch(attributeCode) {
    case 0 : return price;
    case 1 : return cost;
    case 2 : return manDay;
    default: return FTE;
  }
}

然后在你的行动中

public JsonResult _columns(int attributeCode)
{
    var services = db.Services.AsQueryable();
    var jcontainer = new MyJSONContainer();

    foreach(var service in services) 
        jcontainer.addEntry(service.description, service.GetValueFor(attributeCode));

    return Json(jcontainer);

}
于 2013-07-17T10:04:52.207 回答
1

如果您希望将来扩展它,那么我会将这些任务移到他们自己的课程中。

首先是一般的建设者:

static class JsonResultBuilder
{   
    public static JsonResult Build(Database db, int attributeCode)
    {
        var propertyRetriever = JsonServicePropertyRetrievers.Get(attributeCode);

        IQueryable<Service> services = db.Services.AsQueryable();
        MyJSONContainer jcontainer = new MyJSONContainer();

        foreach(Service s in services)
            jcontainer.addEntry(s.Description, propertyRetriever(s));

        return Json(jcontainer);
    }
}

然后是一个单独的类,您可以轻松地添加更多属性检索器:

static class JsonServicePropertyRetrievers
{
    private static readonly Dictionary<int, Func<Service, object>> ServicePropertyRetrievers = new Dictionary<int, Func<Service, object>>();
    private static readonly Func<Service, object> DefaultServicePropertyRetriever;

    static JsonResultBuilder()
    {
        DefaultServicePropertyRetriever = s => s.FTE;

        Register(0, s => s.price);
        Register(1, s => s.cost);
        Register(2, s => s.manDay);
    }

    public static void Register(int attributeCode, Func<Service, object> propertyRetriever)
    {
        ServicePropertyRetrievers[attributeCode] = propertyRetriever;
    }

    public static Func<Service, object> Get(int attributeCode)
    {
        Func<Service, object> propertyRetriever;
        if (!ServicePropertyRetrievers.TryGetValue(attributeCode, out propertyRetriever))
            propertyRetriever = DefaultServicePropertyRetriever;

        return propertyRetriever;
    }
}

这样就没有越来越大的switch语句了。如果您希望动态添加对代码的支持,您可以轻松使用该JsonServicePropertyRetrievers.Register方法。如果您不想公开对此的支持,只需将该方法设为私有即可。如果要删除检索方法,可以添加Remove方法。

如果可能的话,我还建议enum为您实施一个。attributeCode

于 2013-07-17T10:10:37.193 回答