Is it possible to change cast of an object dynamic

2019-08-26 01:15发布

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?

3条回答
神经病院院长
2楼-- · 2019-08-26 01:39

As long as you use the common base class QuickFix.Message you cannot use specific members without casting.

If you have a piece of code where you work with a specific subclass you can do:

if(newOrderSingle is QuickFix.FIX44.NewOrderSingle)
{
    QuickFix.FIX44.NewOrderSingle ord44 = (QuickFix.FIX44.NewOrderSingle)newOrderSingle;
    // from here on you can work with ord44:
    ord44.Set(new Price(limitPrice));

    // more code which uses ord44
}
查看更多
男人必须洒脱
3楼-- · 2019-08-26 01:41

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);
查看更多
趁早两清
4楼-- · 2019-08-26 02:06

if you have access to the source code of QuickFix.Message, you can add it. perhaps you can add the set function to a common interface.

the really dirty way is using reflection. the code would look like this:

newOrderSingle.GetType().GetMethod("Set").Invoke(newOrderSingle, new Price(limitPrice)));

(I guess it will not compile directly, the function parameters needs to be adjusted)

you could also try to use the dynamic datatype

查看更多
登录 后发表回答