Search code examples
c#quickfixfix-protocol

Is it possible to change cast of an object dynamically?


I want have a "pointer" to an object but the object can be one of two classes.

QuickFix.Message newOrderSingle;

            if (ecn.versionFIX.Equals(VersionFIX.FSS_FIX44))
            {
                newOrderSingle = new QuickFix.FIX44.NewOrderSingle(
                    new ClOrdID(masterForm.OrderBook.GetNewClOrdIDBroker(ecn.brokerCode)),
                    new Symbol(symbol),
                    new Side(side),
                    new TransactTime(DateTime.Now),
                    ordType = new OrdType(OrdType.LIMIT));
            }
            else
            {
                newOrderSingle = new QuickFix.FIX42.NewOrderSingle(
                    new ClOrdID(masterForm.OrderBook.GetNewClOrdIDBroker(ecn.brokerCode)),
                    new HandlInst('1'),
                    new Symbol(symbol),
                    new Side(side),
                    new TransactTime(DateTime.Now),
                    ordType = new OrdType(OrdType.LIMIT));
            }

Then later I want to do this, where "set" is a method of QuickFix.FIX44.NewOrderSingle:

newOrderSingle.Set(new Price(limitPrice));

Instead I have to do:

((QuickFix.FIX44.NewOrderSingle) newOrderSingle).Set(new Price(limitPrice));

Which is hard to read.

Can I change "cast" of NewOrderSingle dynamically in some way?


Solution

  • You have some options:

    dynamic

    You can use dynamic keyword to make "duck typing":

    dynamic order= newOrderSingle;
    order.Set(new Price(limitPrice));
    

    Unfortunately, you loose intellisense and will get RuntimeBinderException when order has not such a method (is of type FIX42 f.e.).

    GenericInvoker

    You can use my library:

    newOrderSingle.DetermineType()
                  .When((QuickFix.FIX42 msg) => msg.Set(/* ... */))
                  .Resolve();
    

    Unfortunately, you need to hardcode type.

    To sum up If you need to use such approach, your classes are badly designed. Consider creating base / abstract class or some inteface:

    interface IMessageSetable
    {
        Set(Price p);
    }
    
    public class FIX44 : IMessageSetable
    { 
        // impl
    }
    

    then:

    if (newOrderSingle is IMessageSetable)
          ((IMessageSetable)newOrderSingle).Set(price);