让我们考虑一个用于订单历史记录的域抽象类和考虑付款、取消、重新激活等事件的具体类(以下代码是非常简化的版本)
public abstract class OrderEvent
{
protected OrderEvent(DateTime eventDate)
{
EventDate = eventDate;
}
public abstract string Description { get; }
public DateTime EventDate { get; protected set; }
}
public class CancellationEvent : OrderEvent
{
public CancellationEvent(DateTime cancelDate)
: base(cancelDate)
{
}
public override string Description { get { return "Cancellation"; } }
}
public class PaymentEvent : OrderEvent
{
public PaymentEvent(DateTime eventDate, decimal amount, PaymentOption paymentOption) : base(eventDate)
{
Description = description;
Amount = amount;
PaymentOption = paymentOption;
}
public override string Description { get{ return "Payment"; } }
public decimal Amount { get; protected set; }
public PaymentOption PaymentOption { get; protected set; }
}
现在我必须在此域模型上为我的 ASP.NET MVC 项目构建一个 ViewModel,它将所有事件封装到一个类中,以便在 View 上进行网格展示。
public class OrderHistoryViewModel
{
public OrderHistoryViewModel(OrderEvent orderEvent)
{
// Here's my doubt
}
public string Date { get; protected set; }
public string Description { get; protected set; }
public string Amount { get; protected set; }
}
如何从具体类访问特定属性,例如 PaymentEvent 上的 Amount 属性,而不需要执行 switch 或 if 等一些令人讨厌的事情?
谢谢!
最佳答案
正在做double dispatch假定您使用的是 .NET 4 及更高版本:
public class OrderHistoryViewModel
{
public OrderHistoryViewModel(OrderEvent orderEvent)
{
// this will resolve to appropriate method dynamically
(this as dynamic).PopulateFrom((dynamic)orderEvent);
}
void PopulateFrom(CancellationEvent e)
{
}
void PopulateFrom(PaymentEvent e)
{
}
public string Date { get; protected set; }
public string Description { get; protected set; }
public string Amount { get; protected set; }
}
就我个人而言,我并不介意在这种类型的代码中执行 if/switch 语句。这是应用程序边界代码,不需要非常漂亮,并且使其明确会有所帮助。 C#真正需要的是algebraic type例如union type in F# 。这样,编译器将确保您显式处理所有情况(子类型)。
关于asp.net-mvc - ASP.NET MVC - 多态域类和 View 模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13768442/