C# Quickfix/n,提取消息类型的最有效方法?

C# Quickfix/n,提取消息类型的最有效方法?,c#,quickfix,fix-protocol,C#,Quickfix,Fix Protocol,Quickfix/n 1.4中提取此处定义的消息类型的最有效方法是什么: 我目前使用var msgType=Message.GetMsgType(Message.ToString())这将导致登录消息为“A”。有更好的办法吗?我试图在ToAdmin(…)中确定消息类型,以便捕获传出的登录请求消息,以便添加用户名和密码 我很想通过MessageCracker来实现,但到目前为止,我还没有找到一种方法来实现捕获所有剩余的消息类型,以防我没有实现所有OnMessage重载。(请参阅相关问题:) 谢谢在

Quickfix/n 1.4中提取此处定义的消息类型的最有效方法是什么:

我目前使用
var msgType=Message.GetMsgType(Message.ToString())这将导致登录消息为“A”。有更好的办法吗?我试图在
ToAdmin(…)
中确定消息类型,以便捕获传出的登录请求消息,以便添加用户名和密码

我很想通过MessageCracker来实现,但到目前为止,我还没有找到一种方法来实现捕获所有剩余的消息类型,以防我没有实现所有OnMessage重载。(请参阅相关问题:)


谢谢

在这种情况下,您可以在管理员内部执行此操作:

var logonMessage = msg as Logon;
if (logonMessage != null)
{
    //Treat the logon message as you want
}
或者使用另一个答案中解释的MessageCracker


希望有帮助。

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

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

下面是一组代码,几乎可以将其固定住():


这里是另一种方法,使用我在另一篇文章中提到的想法。实际上,将Crack方法分为两种方法并使用OnMessageTo和OnMessageFrom处理程序非常简单。上面的helper类的修改实现知道消息的方向,但肯定可以改进

在您的应用程序中,实现如下(不是完整的代码):

以及修改后的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);
        }
    }
}
使用系统;
使用System.Collections.Generic;
运用系统反思;
命名空间快速修复
{
/// 
///帮助器类,用于将各种修复版本的消息类型委派给
///类型安全的OnMessage方法,支持分别处理传入和传出消息
/// 
公共抽象类DirectedMessageCracker
{
私有只读字典_toHandlerMethods=新字典();
私有只读词典_fromHandlerMethods=新词典();
受保护的DirectedMessageCracker()
{
初始化(这个);
}
私有void初始化(对象messageHandler)
{
var handlerType=messageHandler.GetType();
var methods=handlerType.GetMethods();
foreach(方法中的var m)
{
if(IsToHandlerMethod(m))
_toHandlerMethods[m.GetParameters()[0].ParameterType]=m;
else if(IsFromHandlerMethod(m))
_fromHandlerMethods[m.GetParameters()[0].ParameterType]=m;
}
}
静态公共布尔IsToHandlerMethod(MethodInfo m)
{
返回IsHandlerMethod(“OnMessageTo”,m);
}
静态公共bool IsFromHandlerMethod(MethodInfo m)
{
返回IsHandlerMethod(“OnMessageFrom”,m);
}
静态公共bool IsHandlerMethod(字符串searchMethodName,MethodInfo m)
{
返回(m.IsPublic)
&&m.Name.StartsWith(searchMethodName)
&&m.GetParameters().Length==2
&&m.GetParameters()[0]。ParameterType.IsubClassOf(消息类型))
&&typeof(SessionID).IsAssignableFrom(m.GetParameters()[1].ParameterType)
&&m.ReturnType==typeof(void));
}
/// 
///处理(“破解”)修复消息并调用该类型的已注册处理程序(如果有)
/// 
/// 
/// 
/// 
私有void破解(IDictionary handlerMethods、Message、SessionID SessionID)
{
var messageType=message.GetType();
方法信息处理程序;
if(handlerMethods.TryGetValue(messageType,out处理程序))
调用(这个,新对象[]{message,sessionID});
其他的
抛出新的不受支持的消息类型();
}
/// 
///处理(“破解”)传入的修复消息,并调用该类型的已注册处理程序(如果有)
/// 
/// 
/// 
public void CrackFrom(消息消息,SessionID SessionID)
{
裂纹(来自HandlerMethods、message、sessionID);
}
/// 
///处理(“破解”)传出的修复消息,并调用该类型的已注册处理程序(如果有)
/// 
/// 
/// 
public void CrackTo(消息消息,SessionID SessionID)
{
裂纹(_-toHandlerMethods、message、sessionID);
}
}
}
如果您不想通过删除
throw new UnsupportedMessageType(),来实现所有可能的消息处理程序,您也可以跳过破解而不是抛出异常来自裂纹方法


另一个想法是拆分破解管理员/应用程序消息。

这是过早的优化。先让它工作。推迟绩效调查,直到你知道你需要它。对不起,我的评论太直截了当了。我想说的是,如果您有性能问题,这个小字符串解析问题不可能是您的主要原因。在有证据证明这是个问题之前,不要担心优化问题。这与性能完全无关。我需要检查发送的消息是否是登录,以便添加用户名和密码。我想我将您使用的“高效”解释为性能。我的错。不用担心,也许“高效”这个词有误导性。谢谢你的回答。正是我想要的。我不知道Tag类。非常感谢。谢谢,但我觉得格兰特的回答稍微优雅一点。谢谢你+1非常感谢这个想法。但是,我搁置了使用MessageCracker的整个想法,因为构建器目前似乎无法为添加的xml数据字典自定义消息类型创建代码。没有它,我也不能使用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
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);
        }
    }
}