Is it possible to change cast of an object dynamically?

北慕城南 提交于 2020-01-07 01:22:38

问题


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?


回答1:


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



回答2:


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




回答3:


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
}


来源:https://stackoverflow.com/questions/29985539/is-it-possible-to-change-cast-of-an-object-dynamically

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!