传递只有 PostSharp 可以看到的 class 对象

Passing a class object that only PostSharp can see

我不确定这是否可行。

我有一个从客户端 api 到服务 api 的方法调用(在两个不同位置的两个不同项目),我希望 post sharp 拦截。调用来自客户端并且 postsharp 在服务中

service.GetLogin(username)

这里的关键是我需要传递一个将在 postsharp onentry 方法中显示的授权对象

 public class Authorization
    {
        public string client_id  { get; set; }
         public string client_secret { get; set; }
        public string access_token { get; set; }
        public string token_type { get; set; }
        public string expires_in { get; set; }
    }

var auth = new Authorization();
 auth.client_id = "xyz";
 auth.client_secret = "abc"

并在 post尖

 [Serializable]
    public class LoggingAspect : OnMethodBoundaryAspect
    {
        public override void OnEntry(MethodExecutionArgs args)
        {
           //I need the object to show up here
        }
    }

问题: 我不想在每个方法调用中都传递这个对象,因为我有 1000 多个方法。有没有办法将该授权对象附加到每个调用,以便 postsharp 可以看到它而无需执行类似这样的操作

service.GetLogin(username, auth);
service.Foo(auth)
service.Bar(auth);
service.xyz(auth);
services.abc(auth);

您能想象仅将这个对象添加到 1000 多个方法中吗?

PostSharp 无法直接使用来自调用站点的数据,因为它需要向方法添加实际参数(或发出新的重载)。这在理论上可以使用 low-level SDK,但难以维护且实施成本高。

实现此目的的最佳方法是使用 AsyncLocal<T>,它允许您将数据存储在 ExecutionContext

public class AuthorizationProvider
{
  private static AsyncLocal<Authorization> state = new AsyncLocal<Authorization>();

  public Authorization Current { get => state.Value; set => state.Value = value; }
}

授权有效的代码将是:

Authorization authorization = ... ;

try
{
  AuthorizationProvider.Current = authorization;
  
  // your logic.
}
finally
{
  AuthorizationProvider.Current = null;
}

然后可以从OnEntry中读取授权对象:

[Serializable]
public class LoggingAspect : OnMethodBoundaryAspect
{
  public override void OnEntry(MethodExecutionArgs args)
  {
    if (!(AuthorizationProvider.Current?.IsValid ?? false))
    {
      ...
    }
  }
}

你也可以将当前Authorization的setting/unsetting包裹在一个IDisposable中,这样你就可以使用using语句。

在 AsyncLocal 中分配的值集存储在执行上下文中,因此通过异步调用流动。存储在执行上下文中的值,在您删除上面 finally 块中的值后可能会被捕获和使用。 See more here.