Получить значение из библиотеки void QuickFix - PullRequest
0 голосов
/ 02 января 2019

У меня есть QuickFix Приложение на C #:

    public class MyQuickFixApp : IApplication
    {
        ...
        public void ToApp(Message msg, SessionID sessionID) 
        { 
            string s = msg.GetString(Tags.ClOrdID);
            ...
        }
        public void FromApp(Message msg, SessionID sessionID) { }
    }

, где сообщение на другой сервер Fix Pack отправляется с ToApp, а ответ поступает на FromApp.
Мне нужно сохранить значение тега отправленного сообщения (s), чтобы выбрать соответствующий ответ.ToApp метод возвращает void.Я пытался сохранить значение в общедоступной статической области, но это не удалось.

Похоже на следующее:

    public class MyQuickFixApp : IApplication
    {
        ...
        public static string currClOrdID = ""; 
        public void ToApp(Message msg, SessionID sessionID) 
        { 
            string s = msg.GetString(Tags.ClOrdID);
            currClOrdID = s;
            ...
        }
        public void FromApp(Message msg, SessionID sessionID) 
        { 
            if (Equals(currClOrdID)) ...
        }
    }

Я получаю NullreferenceException на currClOrdID.Какова общая стратегия сделать это?Пожалуйста, дайте мне несколько советов.

1 Ответ

0 голосов
/ 08 февраля 2019

Согласно QuickFix / n Tutorial :

Лучший способ написать приложение - это использовать специальные строго типизированные классы сообщений и полей

Таким образом, вы можете использовать Crack(...); в FromApp:

using QuickFix;

public class MyApplication : MessageCracker, IApplication
{
    public void FromApp(Message msg, SessionID sessionID)
    {
        Crack(msg, sessionID);
    }
    //...
}

Что касается ClOrdID, вы можете извлечь его из сообщения и напрямую передать его в функцию обработки, это безопаснее, чем хранить ClOrdID в статической переменной при обработке многопоточных сообщений.

Например (при условии, что вам нужно обработать ExecutionReport сообщение):

public void OnMessage(QuickFix.FIX44.ExecutionReport msgReport, SessionID sessionID)
{
    string clOrdID = msgReport.ClOrdID.getValue();
    ...
    YourProcessing(clOrdID, ...);
}

Обратите внимание, что OnMessage(...) будет вызываться из Crack(msg, sessionID);

Если вам необходимо сохранить дополнительные данные для обработки полученного сообщения, я бы использовал словарь, поскольку у вас может быть несколько ожидающих сообщений, а ответы могут поступать в непредсказуемом порядке.Также кажется логичным хранить такие данные близко к (и до) вызову Send, а не к ToApp, как показано ниже (при условии, что вы отправляете ордер на исполнение, ожидая ответа ExecutionReport):

private ConcurrentDictionary<string, ...> _orderData = 
    new ConcurrentDictionary<string, ...>();

public bool PlaceNewOrder(...)
    {
        string clOrdID = ...;
        QuickFix.FIX44.NewOrderSingle msgOrder = 
            new QuickFix.FIX44.NewOrderSingle(new ClOrdID(clOrdID), ...);
        ...;
        _orderData.TryAdd(clOrdID, <data required for later processing>);
        // Notice the data is stored before sending the message
        // so it will be available to process a response
        Session.SendToTarget(msgOrder, sessionID);
    }

При обработке ответного сообщения вы можете получить данные, сохраненные для этого конкретного clOrdID:

private void YourProcessing(clOrdID, ...)
{
    ...;
    _orderData.TryGetValue(clOrdID, out ...);
    // You may want to check return value to make sure the data was stored for this clOrdID...
    ...;
}

Также обратите внимание, что в какой-то момент вы должны очистить словарь, например, когда вы знаете изобработано сообщение, что оно является последним, и не ожидайте больше сообщений для этого ClOrdID.

...