Question

What is the most efficient way in Quickfix/n 1.4 to extract the message type as defined here: http://www.fixprotocol.org/FIXimate3.0/en/FIX.5.0SP2/messages_sorted_by_type.html

I currently use var msgType = Message.GetMsgType(message.ToString()); which results in "A" for a Logon message. Is there a better way? I try to determine the message type within ToAdmin(...) in order to catch an outgoing Logon request message so I can add the username and password.

I would love to do it through MessageCracker but so far I have not found a way to implement a catch-all-remaining message types in case I have not implemented all OnMessage overloads. (Please see related question: Quickfix, Is there a "catch-all" method OnMessage to handle incoming messages not handled by overloaded methods?).

Thanks

Was it helpful?

Solution

Not your title question, but a key part of it:

I try to determine the message type within ToAdmin(...) in order to catch an outgoing Logon request message so I can add the username and password.

Here's a blob of code that pretty much nails it (taken from this post to the QF/n mailing list):

    public void ToAdmin(Message message, SessionID sessionID)
    {
        // Check message type
        if (message.Header.GetField(Tags.MsgType) == MsgType.LOGON)
        {
            // Yes it is logon message
            // Check if local variables YourUserName and YourPassword are set
            if (!string.IsNullOrEmpty(YourUserName) && !string.IsNullOrEmpty(YourPassword))
            {
                // Add Username and Password fields to logon message
                ((Logon) message).Set(new Username(YourUserName));
                ((Logon) message).Set(new Password(YourPassword));
            }
        }
    }

OTHER TIPS

Here is another approach using the idea I've mentioned in the other post. It's actually very simple to split the Crack method in two methods and have OnMessageTo and OnMessageFrom handlers. The modified implementation of the MessageCracker helper class above is aware about the message direction, though certainly can be improved.

In your Application, implement like this (not complete code):

public class MyFixApplication: DirectedMessageCracker, Application
{
...

public void FromAdmin(Message msg, SessionID sessionId)
{
    CrackFrom(msg, sessionId);
}

public void ToAdmin(Message msg, SessionID sessionId)
{
    CrackTo(msg, sessionId);
}

public void OnMessageTo(Logon msg, SessionID sessionId)
{
    //Treat the outgoing message, set user, password, etc
}

public void OnMessageFrom(Allocation msg, SessionID sessionId)
{
    //Treat the incoming Allocation message
}
...and so on

And the modified MessageCracker:

using System;
using System.Collections.Generic;
using System.Reflection;

namespace QuickFix
{
    /// <summary>
    /// Helper class for delegating message types for various FIX versions to
    /// type-safe OnMessage methods, supports handling of incoming and outgoing messages separatelly
    /// </summary>
    public abstract class DirectedMessageCracker
    {
        private readonly Dictionary<Type, MethodInfo> _toHandlerMethods = new Dictionary<Type, MethodInfo>();
        private readonly Dictionary<Type, MethodInfo> _fromHandlerMethods = new Dictionary<Type, MethodInfo>();

        protected DirectedMessageCracker()
        {
            Initialize(this);
        }

        private void Initialize(Object messageHandler)
        {
            var handlerType = messageHandler.GetType();

            var methods = handlerType.GetMethods();
            foreach (var m in methods)
            {
                if (IsToHandlerMethod(m))
                    _toHandlerMethods[m.GetParameters()[0].ParameterType] = m;
                else if (IsFromHandlerMethod(m))
                    _fromHandlerMethods[m.GetParameters()[0].ParameterType] = m;
            }
        }

        static public bool IsToHandlerMethod(MethodInfo m)
        {
            return IsHandlerMethod("OnMessageTo", m);
        }

        static public bool IsFromHandlerMethod(MethodInfo m)
        {
            return IsHandlerMethod("OnMessageFrom", m);
        }

        static public bool IsHandlerMethod(string searchMethodName, MethodInfo m) 
        {
            return (m.IsPublic
                && m.Name.StartsWith(searchMethodName)
                && m.GetParameters().Length == 2
                && m.GetParameters()[0].ParameterType.IsSubclassOf(typeof(Message))
                && typeof(SessionID).IsAssignableFrom(m.GetParameters()[1].ParameterType)
                && m.ReturnType == typeof(void));
        }

        /// <summary>
        /// Process ("crack") a FIX message and call the registered handlers for that type, if any
        /// </summary>
        /// <param name="handlerMethods"></param>
        /// <param name="message"></param>
        /// <param name="sessionID"></param>
        private void Crack(IDictionary<Type, MethodInfo> handlerMethods, Message message, SessionID sessionID)
        {
            var messageType = message.GetType();
            MethodInfo handler;

            if (handlerMethods.TryGetValue(messageType, out handler))
                handler.Invoke(this, new object[] { message, sessionID });
            else
                throw new UnsupportedMessageType();
        }

        /// <summary>
        /// Process ("crack") an INCOMING FIX message and call the registered handlers for that type, if any
        /// </summary>
        /// <param name="message"></param>
        /// <param name="sessionID"></param>
        public void CrackFrom(Message message, SessionID sessionID)
        {
            Crack(_fromHandlerMethods, message, sessionID);
        }

        /// <summary>
        /// Process ("crack") an OUTGOING FIX message and call the registered handlers for that type, if any
        /// </summary>
        /// <param name="message"></param>
        /// <param name="sessionID"></param>
        public void CrackTo(Message message, SessionID sessionID)
        {
            Crack(_toHandlerMethods, message, sessionID);
        }
    }
}

You can also skip the crack instead of throwing an exception in case of you don't want to implement all possible message handlers by just removing the throw new UnsupportedMessageType(); from the crack method.

Another idea is to split cracking Admin/App messages.

In this case you could just do this inside ToAdmin:

var logonMessage = msg as Logon;
if (logonMessage != null)
{
    //Treat the logon message as you want
}

Or use the MessageCracker as explained in the other answer that you mentioned.

Hope it helps.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top