如何重构此代码以使其更通用?

时间:2013-10-19 21:06:08

标签: c# refactoring

我有以下模板存储在文本文件中:

  

您好,感谢您购买{year} {make} {model}。

year, make, and model来源存储在template configuration table中,实际值存储在Car table中。

目前,我获取了要在模板(year, make, and model)中使用的所有字段,然后从Car表中获取它们的值,并将令牌({year}, {make}, {model})替换为来自数据库的值,所以最终看起来像是:

  

您好,感谢您购买2013 Honda Civic。

当所有内容都来自Car表时,这一切都很好,因为如果模板添加需要一个新字段,例如{color},我只需将其添加到template configuration table,一切正常, template configuration table是每个用户,因此如果一个用户不想要{color},则可以轻松完成。我遇到的问题是数据不是来自Car,而是可能来自其他表,例如:

  

您好,感谢您购买{year} {make} {model}。

     

您的订单号是{order_no},您可以联系

     如果您有任何问题,请在{customer_service_number}处获得客户服务。

为了这个例子,我们假设{order_no}来自orders表而{customer_service_number}来自CustomerService表。

我在考虑使用这样的方法:

var text = @"Hello, Thanks for Buying the {year} {make} {model}.
Your order number is {order_no} and you can contact customer service at {customer_service_number} if you have any problems.";

//This is for fields that are found directly on the Car object
foreach(var field in templateFields)
{
    var val = car.GetType().GetProperty(field).GetValue(car,null);

    text = text.Replace(field, val);
}

//Replace other fields
var order_no = order.GetOrderNo();

text = text.Replace("{order_no}",order_no);

var customer_service_number = customerService.GetCustomerServiceNumber();

text = text.Replace("{customer_service_number}",customer_service_number);

如果每个人都希望看到额外的字段,上面的工作正常,但如果只有几个用户想看到order_no and/or the customer_service_number部分,那么调用其中一个或两个都是没有意义的。

此外,如果客户想要查看其他信息,那么我必须再次拨打电话:

text = text.Replace("{number_of_oil_changes}",car.NumberOfOilChanges);

然后我最终会得到一些有用的和/或无用的方法,具体取决于客户,那么我怎样才能避免编写所有这些额外的方法来获取依赖于客户的信息呢?

1 个答案:

答案 0 :(得分:2)

我认为这可能是您应该实际采用 less 通用方法的情况,因为用户界面通常不是通用的。例如,您可能稍后意识到,想要在没有年份的情况下查看模型的客户应该以与查看年份的客户不同的格式查看模型。这些是不同的屏幕,因此可能有不同的规则,并且具有特定于每个屏幕的代码将使以后的工作更容易。

我会创建一个专门针对模板需求量身定制的扁平结构。这甚至包括直接来自Car的字段,因为这意味着如果表结构发生变化,您将不需要更新模板。假设您将“模型”拆分为两列以便于过滤或在某些情况下 - 在这种情况下,您只需要更新结构,以便将“模型”字段设置为model1 + model2,而不是将所有模板更改为{ {1}}。

为避免加载冗余信息,您可以随时检查模板中包含的字段。在我看来,更好的方法是使用一个具有“懒惰”属性的类作为模板结构(属性的值仅在第一次请求时才加载):

{model1}{model2}

使用这样的类,您可以通过在类上查找匹配的属性来动态替换模板中的每个class OrderDisplay { private readonly Order _order; public OrderDisplay(Order order) { _order = order; } private string _orderNo; public string OrderNo { get { if (_orderNo == null) _orderNo = _order.GetOrderNo(); return _orderNo; } } ...other properties... } 。每当模板不包含某些属性时,它们自然不会被调用。