我目前正在寻找将PostSharp日志记录(可能还有其他自定义方面)添加到ASP.NET Core API项目中的方法。我遇到的问题是,我们有一个多租户设计,其中的租户信息存储在用户声明中,而且似乎没有从PostSharp方面获取当前会话的好方法,因此似乎不是访问适当租户数据库的好方法。
我只是在吠错一棵树吗?我应该看看其他的AOP框架吗?
答案 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属性没有作用,该服务也将针对该请求。不会出现在我们的源代码中。