6

Quickfix/n 1.4 中提取此处定义的消息类型的最有效方法是什么:http ://www.fixprotocol.org/FIXimate3.0/en/FIX.5.0SP2/messages_sorted_by_type.html

我目前使用var msgType = Message.GetMsgType(message.ToString());的结果是“A”作为登录消息。有没有更好的办法?我尝试确定其中的消息类型ToAdmin(...)以捕获传出的登录请求消息,以便添加用户名和密码。

我很想通过 MessageCracker 来做到这一点,但到目前为止,我还没有找到一种方法来实现一个捕获所有剩余消息类型的方法,以防我没有实现所有 OnMessage 重载。(请参阅相关问题:Quickfix,是否有一个“包罗万象”的方法 OnMessage 来处理未由重载方法处理的传入消息?)。

谢谢

4

3 回答 3

5

不是您的标题问题,而是其中的关键部分:

我尝试确定 ToAdmin(...) 中的消息类型,以便捕获传出的登录请求消息,以便添加用户名和密码。

这是一段代码,几乎可以确定它(取自这篇文章到 QF/n 邮件列表):

    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));
            }
        }
    }
于 2013-07-31T13:50:26.327 回答
2

这是使用我在另一篇文章中提到的想法的另一种方法。将 Crack 方法拆分为两个方法并拥有 OnMessageTo 和 OnMessageFrom 处理程序实际上非常简单。上面MessageCracker助手类的修改实现知道消息方向,当然可以改进。

在您的应用程序中,像这样实现(不完整的代码):

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

以及修改后的 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);
        }
    }
}

如果您不想通过throw new UnsupportedMessageType();从破解方法中删除 来实现所有可能的消息处理程序,您也可以跳过破解而不是抛出异常。

另一个想法是拆分破解 Admin/App 消息。

于 2013-08-01T19:55:17.883 回答
1

在这种情况下,您可以在 ToAdmin 中执行此操作:

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

或者按照您提到的其他答案中的说明使用 MessageCracker 。

希望能帮助到你。

于 2013-07-31T13:40:48.657 回答