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来实现它,但到目前为止,我还没有找到一种方法来实现一个catch-all-remaining消息类型,以防我没有实现所有的OnMessage重载。 (请参阅相关问题:Quickfix, Is there a "catch-all" method OnMessage to handle incoming messages not handled by overloaded methods?)。
由于
答案 0 :(得分:4)
不是你的头衔问题,而是其中的关键部分:
我尝试确定ToAdmin(...)中的消息类型,以便捕获传出的登录请求消息,以便我可以添加用户名和密码。
这里有一大堆代码(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));
}
}
}
答案 1 :(得分:2)
这是使用我在另一个post中提到的想法的另一种方法。实际上,在两种方法中拆分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);
}
}
}
如果你不想通过从crack方法中删除throw new UnsupportedMessageType();
来实现所有可能的消息处理程序,你也可以跳过破解而不是抛出异常。
另一个想法是拆分破解管理员/应用程序消息。
答案 2 :(得分:1)
在这种情况下,您可以在ToAdmin中执行此操作:
var logonMessage = msg as Logon;
if (logonMessage != null)
{
//Treat the logon message as you want
}
或者按照you mentioned。
的其他答案中的说明使用MessageCracker希望它有所帮助。