是否可以动态更改对象的转换?

Is it possible to change cast of an object dynamically?

我想要一个 "pointer" 对象,但该对象可以是两个 类 之一。

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

那以后我想做这个,其中"set"是QuickFix.FIX44.NewOrderSingle的一个方法:

newOrderSingle.Set(new Price(limitPrice));

相反,我必须这样做:

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

很难读。

我可以通过某种方式动态更改 NewOrderSingle 的 "cast" 吗?

如果您能访问QuickFix.Message的源代码,您可以添加它。也许您可以将设置功能添加到通用界面。

真正肮脏的方法是使用反射。代码如下所示:

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

(估计不会直接编译,需要调整函数参数)

您也可以尝试使用 dynamic 数据类型

您有一些选择:

动态

您可以使用 dynamic 关键字使 "duck typing":

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

不幸的是,当 order 没有这样的方法(属于 FIX42 f.e. 类型)时,您失去了智能感知并会得到 RuntimeBinderException

GenericInvoker

你可以使用我的 library:

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

不幸的是,您需要硬编码类型。

总结 如果您需要使用这种方法,那么您的 classes 设计得很糟糕。考虑创建基础/抽象 class 或一些接口:

interface IMessageSetable
{
    Set(Price p);
}

public class FIX44 : IMessageSetable
{ 
    // impl
}

然后:

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

只要您使用公共基数 class QuickFix.Message 就不能使用特定成员而不进行强制转换。

如果您有一段代码可以处理特定的子程序class,您可以这样做:

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
}