我目前正在开发一个带有数据库的项目,其中我有几个只包含类型枚举的表。比如:
OrderStatus:
ID | Description
1 | Open
2 | Shipped
3 | Canceled
...
当我从数据库中获取类型并希望在代码中检查它们时,这通常会导致switch语句,这有点难以维护,尤其是在将新项目添加到表中时。
switch(order.OrderStatus.ID) {
case 1:
handleOpenOrder();
break;
case 2:
handleShippedOrder();
break;
case 3:
handleCanceledOrder();
break;
default:
break;
}
通常会使用继承来解决这个问题,但在这种情况下,我必须检查某些时候从数据库返回的值的类型。
我目前从数据库获取orderstatus作为普通的orderstatus实体。有没有办法让ORM(NHibernate)自动将实体转换为更具体的对象?比如OrderStatusOpen类?
答案 0 :(得分:0)
如果订单处理程序都包含在一个类中并且只在那里使用,那么您可以简单地执行以下操作,并在实现新的处理程序方法时扩展Dictionary<int, Action>
:
public class Foo
{
private readonly _handlerMap = new Dictionary<int, Action>
{
{ 1, () => handleOpenOrder() },
{ 2, () => handleShippedOrder() },
{ 3, () => handleCanceledOrder() }
}
public void TheMethodPreviouslyContainingTheSwitch(Order order)
{
var action = _handlerMap[order.OrderStatus.ID];
action.Invoke();
}
}
如果你在几个类中有switch语句,我可能会为每个处理程序实现一个类并提取一个匹配的接口。如有必要,我可以详细说明。
修改强>
我想到的基于接口的方法基本相同。这可能仍然不是一切的答案;-) 我是从头开始编写的(可能无法编译):
public interface IOrderHandler
{
int StatusId { get; }
void Handle(Order order);
}
public class OpenOrderHandler : IOrderHandler
{
public int StatusId => 1;
public void Handle(Order order)
{
// ...
}
}
public class OrderHandlerFactory
{
// this factory could be injected to all you dependant classes that need
// handlers to handle orders
private readonly _handlerMap = new Dictionary<int, Action>
{
// defining the IDs here and in the classes' defintions may be a bit
// redudant, but... meh ;)
{ 1, () => new OpenOrderHandler() },
{ 2, () => new ShippedOrderHandler() },
{ 3, () => new CancledOrderHandler() }
}
public IOrderHandler CreateHandlerByStatus(int orderStatusId)
{
// if the creation of a handler is expensive, it may be useful to
// only create a single handler that matches the orderStatusId
var action = _handlerMap[orderStatusId];
var handler = action.Invoke();
return handler;
}
public ICollection<IOrderHandler> CreateHandlers()
{
// it may be fine to create all handlers in each call of this method
// if the creation is inexpensive
return _handlerMap.Select(kvp => kvp.Value.Invoke()).ToList();
}
}
public class Foo
{
private readonly OrderHandlerFactory _orderHandlerFactory;
public Foo(OrderHandlerFactory orderHandlerFactory)
{
_orderHandlerFactory = orderHandlerFactory;
}
public void TheMethodPreviouslyContainingTheSwitch(Order order)
{
var handler = _orderHandlerFactory.CreateHandlerByStatus(order.OrderStatus.ID);
handler.Handle(order);
}
public void ThisMayBeUsefulIfMultipleHandlersRelateToAcertainStatus(Order order)
{
var handlers = _orderHandlerFactory.CreateHandlers();
handlers
.Where(handler => handler.StatusId == order.OrderStatus.ID)
.All(handler => handler.Handle(order));
}
}