多租户解决方案中的PostSharp

时间:2019-04-03 13:07:47

标签: c# asp.net-core postsharp

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

我只是在吠错一棵树吗?我应该看看其他的AOP框架吗?

1 个答案:

答案 0 :(得分:1)

出于完整性考虑,这是我想出的解决方案,它同时使用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属性没有作用,该服务也将针对该请求。不会出现在我们的源代码中。