2013-07-31 5 views
3

Что является наиболее эффективным способом в QuickFix/п 1.4 для извлечения типа сообщения, как определено здесь: http://www.fixprotocol.org/FIXimate3.0/en/FIX.5.0SP2/messages_sorted_by_type.htmlQuickfix/n, самый эффективный способ извлечения типа сообщения?

Я в настоящее время использую var msgType = Message.GetMsgType(message.ToString());, что приводит к «A» для сообщения входа в системе. Есть ли способ лучше? Я пытаюсь определить тип сообщения в пределах ToAdmin(...), чтобы поймать исходящее сообщение с запросом на вход, чтобы добавить имя пользователя и пароль.

Я бы хотел сделать это через MessageCracker, но до сих пор я не нашел способ реализовать все остающиеся типы сообщений, если я не реализовал все перегрузки OnMessage. (См. Соответствующий вопрос: Quickfix, Is there a "catch-all" method OnMessage to handle incoming messages not handled by overloaded methods?).

Благодаря

+0

Это преждевременная оптимизация. Сделайте это первым. Отложите исследования эффективности, пока не узнаете, что вам это нужно. –

+0

Извините, мой комментарий был слишком тупым. Я хотел сказать, что если у вас проблемы с производительностью, эта небольшая синтаксическая обработка строк вряд ли будет вашей основной причиной. Не беспокойтесь о том, чтобы оптимизировать вещи, пока не появится доказательство того, что это проблема. –

+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)); 
      } 
     } 
    } 
+0

Отлично. Именно то, что я искал. Я не знал о классе Tag. Большое спасибо. –

1

В этом случае вы можете просто сделать это внутри ToAdmin:

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

Или используют MessageCracker, как описано в другом ответе, что you mentioned.

Надеюсь, это поможет.

+0

Спасибо, но я нашел ответ Гранта немного более изящным. Спасибо хоть. +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); 
     } 
    } 
} 

Вы также можете пропустить трещину вместо того, чтобы выбросить исключение в случае вы не хотите внедрять все возможные обработчики сообщений, просто удалив throw new UnsupportedMessageType(); из метода трещины.

Еще одна идея - разбить трещины на сообщения администратора/приложения.

+0

Большое спасибо за идею. Тем не менее, я поставил всю мысль об использовании MessageCracker на удержании, потому что в настоящее время разработчик не может создать код для добавленных типов сообщений пользовательских словарей данных XML. Без этого я не могу использовать MessageCracker и, скорее, просто сам создавать сообщения. По-прежнему он играет с ним, но до сих пор не выглядит так, как если бы методы сообщений были правильно добавлены в соответствующее пространство имен FIXxx. –