2015-01-26 5 views
2

Я добавил значение в словарь InvocationContext, однако он не сохраняется для следующего вызова. то есть каждый вызов в цепочке, которая перехвачена, возвращает false для InvocationContext.ContainsKey("tracing-id").InvocationContext не сохраняется содержание

public IMethodReturn Invoke(IMethodInvocation input, GetNextInterceptionBehaviorDelegate getNext) 
{ 
    Guid tracingId; 

    if (!input.InvocationContext.ContainsKey(TRACING_ID)) 
    { 
     tracingId = _tracingIdProvider.NewTracingId(); 
     input.InvocationContext.Add(TRACING_ID, tracingId); 
    } 
    else 
    { 
     tracingId = (Guid)input.InvocationContext[TRACING_ID]; 
    } 

    var methodReturn = getNext()(input, getNext); 

    return methodReturn; 
} 

Я могу добавить запись в InvocationContext, однако, когда getNext()(input, getNext) вызывается и следующий вызов перехватили InvocationContext пуст.

Я не понимаю, как используется InvocationContext? Если да, то каков правильный способ сохранить что-то вроде идентификатора от одного вызова метода к следующему?

+0

Какой перехватчик вы используете? – cynic

+0

«InterfaceInterceptor» – BanksySan

+0

Я кратко рассмотрел исходный код Unity, и перехват интерфейса является наименее читаемым из-за того, что все генерирование кода происходит. Можете ли вы попробовать с прозрачным прокси-перехватчиком или перехватчиком виртуальных методов, если это возможно? Если эти работы, реализация перехвата интерфейса может просто иметь ошибку. В любом случае вы можете использовать локальное хранилище потоков или встроенный CallContext для достижения желаемого. – cynic

ответ

2

Мои тесты показывают, что содержимое объекта InvocationContext сохраняется только во время одного вызова. Это означает, что ваш код будет работать только в том случае, если зарегистрировано много зарегистрированных типов поведения. Они будут вызываться один за другим для одного и того же вызова метода, и они могут использовать InvocationContext для обмена данными. Однако, как вы заметили, для следующего звонка InvocationContext будет очищен.

У меня нет большого опыта работы с Unity, поэтому я не знаю, что является рекомендуемым обходным решением. Вы можете подумать о создании своего собственного контекста вызова и реализовать его как одноэлементный. Благодаря этому все вызовы будут иметь доступ к одному экземпляру, и TRACING_ID будет сохраняться во всех вызовах. Он должен работать.

Однако вопрос заключается в том, когда контекст вызова должен быть очищен. Если вы этого не сделаете, все вызовы будут иметь тот же TRACING_ID. Это не имеет смысла. Например, вы можете сбросить TRACING_ID, когда выполняется конкретный метод, отвечающий за запуск обработки (бизнес-сценарий).

+0

Хорошее место, действительно кажется, что контекст сохраняется между вызовами поведения, но * не * вниз по стеку вызовов. Это объясняет одно, но все еще оставляет оставшийся вопрос. Как сохранить идентификатор в стеке вызовов? – BanksySan

+0

@BanksySan - В моем ответе я также предложил обходной путь, то есть _ «... создать свой собственный контекст вызова и реализовать его как одноэлементный.». Это другой подход, чем тот, который предлагается @cynic, но общая идея аналогична т.е. вам нужен глобальный контейнер для хранения данных через вызовы. Вы также можете рассмотреть возможность изменения исходного кода Unity. В настоящее время для каждого нового вызова создается новый 'InvocationContext', поэтому вы можете попробовать добавить новое свойство (например,« GlobalInvocationContext »), которое будет сохраняться во всех вызовах. Однако, если TLS, предложенный @cynic, работает, вы просто используете его. –

+0

Глобальный контейнер будет работать, однако, как я узнаю, когда его заполнить или очистить? Я имею в виду, как бы я узнал, что это новая цепочка звонков? – BanksySan