如何保持拦截器相互关联?
How to keep interceptors related to each other?
我使用 autofac 和 castle 创建了一些用于请求记录、响应记录和异常的拦截器。一些方法可以有请求日志和一些响应日志或两者都有。我想将请求与异常和响应联系起来。
我的意思是我想将请求id传递给其他拦截器。我不想将所有这些都放在一个拦截器中。有没有办法在同一调用中从调用或共享变量中获取唯一 ID?
让我们检查下面的代码,我想在日志之前和之后访问相同的 id 来连接。
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");
}
}
提前致谢。
要为实际请求获取唯一标识符,您可以引入一个将提供此标识符的新服务。
例如我们称它为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,也可以使用 HttpContext.TraceIdentifier
属性;
HttpContext
public class HttpContextIdentifier : IContextIdentifier
{
public SimpleContextIdentifier(IHttpContextAccessor httpContextAccessor)
{
this._httpContextAccessor = httpContextAccessor;
}
private readonly IHttpContextAccessor _httpContextAccessor;
public String Identifier => this._httpContextAccsor.TraceIfentifier;
}
据我所知,没有内置解决方案可以使用Castle.Core拦截框架获取当前方法调用标识符。但是您可以在 IInvocation
实例上使用 ConditionalWeakTable
来获取唯一标识符。
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>
我没有尝试过这个解决方案,但它应该有效。
我使用 autofac 和 castle 创建了一些用于请求记录、响应记录和异常的拦截器。一些方法可以有请求日志和一些响应日志或两者都有。我想将请求与异常和响应联系起来。
我的意思是我想将请求id传递给其他拦截器。我不想将所有这些都放在一个拦截器中。有没有办法在同一调用中从调用或共享变量中获取唯一 ID?
让我们检查下面的代码,我想在日志之前和之后访问相同的 id 来连接。
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");
}
}
提前致谢。
要为实际请求获取唯一标识符,您可以引入一个将提供此标识符的新服务。
例如我们称它为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,也可以使用 HttpContext.TraceIdentifier
属性;
HttpContext
public class HttpContextIdentifier : IContextIdentifier
{
public SimpleContextIdentifier(IHttpContextAccessor httpContextAccessor)
{
this._httpContextAccessor = httpContextAccessor;
}
private readonly IHttpContextAccessor _httpContextAccessor;
public String Identifier => this._httpContextAccsor.TraceIfentifier;
}
据我所知,没有内置解决方案可以使用Castle.Core拦截框架获取当前方法调用标识符。但是您可以在 IInvocation
实例上使用 ConditionalWeakTable
来获取唯一标识符。
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>
我没有尝试过这个解决方案,但它应该有效。