多租户解决方案中的 PostSharp

PostSharp in a multitenant solution

我目前正在寻求将 PostSharp 日志记录(以及可能的其他自定义方面)添加到 ASP.NET Core API 项目中。我 运行 遇到的问题是我们有一个多租户设计,其中租户信息存储在用户声明中,并且似乎没有从 PostSharp 方面获取当前会话的好方法, 因此似乎没有访问正确租户数据库的好方法。

我是不是找错人了?是否有其他我应该关注的 AOP 框架?

为了完整起见,这是我想出的解决方案,它同时使用了 PostSharp 和 AutoFac。

PostSharp 方面可以在编译时应用的 类 上创建属性。使用 AutoFac 的 InjectUnsetProperties 函数,我们可以将适当范围的成员注入这些 类 即使我们在编译时不知道它们 .

因此,我们设置了 PostSharp 方面:

    [PSerializable]
    public class LoggingAspect : OnMethodBoundaryAspect, IInstanceScopedAspect
    {
        [IntroduceMember(Visibility = Visibility.Public, OverrideAction = MemberOverrideAction.Ignore)]
        [CopyCustomAttributes(typeof(ImportMemberAttribute))]
        public IInjectedObject InjectedObject { get; set; }

        [ImportMember("InjectedObject", IsRequired = true)]
        public Property<IInjectedObject> InjectedObjectProperty;

        public override void OnEntry(MethodExecutionArgs args)
        {
            var data = InjectedObjectProperty.Get().MyData;

            Debug.Print($"OnEntry: {args.Method.Name}, Data: {data}\n");
        }

        public object CreateInstance(AdviceArgs adviceArgs)
        {
            return MemberwiseClone();
        }

        public void RuntimeInitializeInstance()
        {
        }
    }

然后在我们的 Startup 方法中注册我们要使用方面的服务:

public IServiceProvider ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_2);

    var builder = new ContainerBuilder();
    builder.Populate(services);

    builder.RegisterType<TestService>().As<ITestService>()
        .InstancePerLifetimeScope()
        .OnActivated(e => e.Context.InjectUnsetProperties(e.Instance))
        ;
    builder.RegisterType<InjectedObject>().As<IInjectedObject>()
        .InstancePerLifetimeScope()
        ;

    var container = builder.Build();

    return new AutofacServiceProvider(container);
}

并将方面添加到我们要记录的方法中:

public class TestService : ITestService
{
    public TestService()
    {
        Debug.Print("TestService ctor\n");
    }

    private int _myData = 100;

    [LoggingAspect]
    public int GetData()
    {
        return _myData++;
    }
}

在请求期间创建服务时,会创建一个范围为该请求的新服务,并且它会插入一个新的 IInjectedObject ,该服务的范围也为请求,即使 IInjectedObject 属性 没有出现在我们的源代码中。