Как сохранить перехватчики, связанные друг с другом? - PullRequest
2 голосов
/ 08 апреля 2020

Я создал несколько перехватчиков для регистрации запросов, регистрации ответов и исключения с autofa c и замком. Некоторые методы могут иметь журналы запросов и некоторые журналы ответов или оба. Я хочу связать запросы с исключениями и ответами.

Я хочу передать идентификатор запроса другим перехватчикам. Я не хочу держать их всех в одном перехватчике. Есть ли способ получить уникальный идентификатор из вызова или совместно используемой переменной при одном и том же вызове?

Давайте проверим код ниже, я хочу получить доступ к тому же идентификатору для связи до и после журналов.

public class BeforeAspect : IInterceptor
{
    public BeforeAspect()
    {

    }
    public void Intercept(IInvocation invocation)
    {
        System.Diagnostics.Debug.WriteLine("some id on before");

        invocation.Proceed();
    }
}
public class AfterAspect : IInterceptor
{
    public AfterAspect()
    {

    }
    public void Intercept(IInvocation invocation)
    {
        invocation.Proceed();

        System.Diagnostics.Debug.WriteLine("exact id like before");
    }
}

Заранее спасибо.

1 Ответ

1 голос
/ 08 апреля 2020

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

Например, назовем его IContextIdentifier

public interfac IContextIdentifier
{
    String Identifer { get; }
}

И

public class BeforeAspect : IInterceptor
{
    public BeforeAspect(IContextIdentifier contextIdentifier)
    {
        this._contextIdentifier = contextIdentifier; 
    }

    private readonly IContextIdentifier _contextIdentifier; 


    public void Intercept(IInvocation invocation)
    {
        System.Diagnostics.Debug.WriteLine($"id is {this._contextIdentifier.Identifier}");

        invocation.Proceed();
    }
}

. Конкретная реализация IContextIdentifier может быть простой:

public class SimpleContextIdentifier : IContextIdentifier 
{
    public SimpleContextIdentifier()
    {
        this.Identifier = Guid.NewGuid().ToString(); 
    }
    public String Identifier { get; private set; }
}

Затем вы регистрируете ContextIdentifier как InstancePerLifetimeScope, чтобы иметь уникальный экземпляр для каждого запроса.

builder.RegisterType<SimpleContextIdentifier>()
       .As<IContextIDentifier>()
       .InstancePerLifetimeScope();

Вы также можете использовать свойство HttpContext.TraceIdentifier, если у вас есть доступ к HttpContext; HttpContext

public class HttpContextIdentifier : IContextIdentifier 
{
    public SimpleContextIdentifier(IHttpContextAccessor httpContextAccessor)
    {
        this._httpContextAccessor = httpContextAccessor; 
    }

    private readonly IHttpContextAccessor _httpContextAccessor;

    public String Identifier => this._httpContextAccsor.TraceIfentifier; 
}

Насколько мне известно, не существует встроенного решения для получения текущего идентификатора вызова метода с использованием Castle.Core инфраструктуры перехвата. Но вы можете использовать ConditionalWeakTable в экземпляре IInvocation, чтобы получить уникальный идентификатор.

public class MethodCallIdentifier<T> : IMethodCallIdentifier
    where T : class
{

    private class Key
    {
        public Key()
        {
            this.Id = Guid.NewGuid();
        }
        public Guid Id { get; private set; }
    }

    public MethodCallIdentifier()
    {
        this._identifiers = new ConditionalWeakTable<T, Key>();
    }

    private readonly ConditionalWeakTable<T, Key> _identifiers;

    public Guid GetUniqueIdentifier(T obj)
    {
        Key key = this._identifiers.GetOrCreateValue(obj);
        return key.Id;
    }
}

Вы должны зарегистрировать MethodCallIdentifier как один экземпляр

builder.RegisterGeneric(typeof(MethodCallIdentifier<>))
       .As(typeof(IMethodCallIdentifier<>))
       .SingleInstance;

, и тогда ваши перехватчики могут зависеть от IMethodCallIdentifier<IInvocation>

Я не пробовал это решение, но оно должно работать.

...