是否可以动态更改对象的转换?
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
}
我想要一个 "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
}