问题
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