2

Let's consider a domain abstract class for an order history and concrete classes considering events such like payments, cancellations, reactivations etc (the following code is a VERY simplified version)

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; }
}

Now I have to build a ViewModel for my ASP.NET MVC project upon this domain model that will encapsulate all the events into a single class for a grid exhibition on the 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; }
}

How can I access the specific properties from concrete classes, like the Amount property on PaymentEvent without doing some smelly thing like switch or if?

Thanks!

1 Answer 1

2

On way is to do double dispatch granted that you're on .NET 4 and above:

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; }
}

Personally, I don't really mind doing if/switch statements in this type of code. This is application boundary code that doesn't need to be very pretty and having it be explicit can be helpful. What C# really needs are algebraic types such as the union type in F#. This way, the compiler will ensure that you handle all cases (sub-types) explicitly.

Sign up to request clarification or add additional context in comments.

1 Comment

Keep getting error that the best overload method for TYPE has some invalid arguments. :-\

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.