我有这样的方面:
[PSerializable]
[AttributeUsage( AttributeTargets.Class | AttributeTargets.Struct | AttributeTargets.Interface | AttributeTargets.Method | AttributeTargets.Constructor | AttributeTargets.Property | AttributeTargets.Event, AllowMultiple = false )]
public abstract class LogAttribute : OnMethodBoundaryAspect, IInstanceScopedAspect {
// CompileTime/Init
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo) {
}
// CompileTime/Validate
public override bool CompileTimeValidate(MethodBase method) {
return true;
}
// Runtime/Init/Static
public override void RuntimeInitialize(MethodBase method) {
}
// Runtime/Init/Instance (Only if method is not static)
object IInstanceScopedAspect.CreateInstance(AdviceArgs args) {
var clone = (LogAttribute) MemberwiseClone();
return clone;
}
void IInstanceScopedAspect.RuntimeInitializeInstance() {
}
// Advices
public override void OnEntry(MethodExecutionArgs args) {
}
public override void OnSuccess(MethodExecutionArgs args) {
}
public override void OnException(MethodExecutionArgs args) {
}
public override void OnExit(MethodExecutionArgs args) {
}
public override void OnYield(MethodExecutionArgs args) {
}
public override void OnResume(MethodExecutionArgs args) {
}
}
我将其用于非静态和静态方法和类。但是现在我不能在静态类中使用IInstanceScopedAspect
!
我遇到错误:Error LA0203 Cannot apply instance-level aspect "LogAttribute" to static class "...".
发生了什么变化?我现在该怎么办?
这在PostSharp 6.4中是不允许的,因为有可能以违反C#对静态类(添加的实例成员等)的定义的方式更改方面的目标类。现在正确的方法是,如果需要使用IInstanceScopedAspect
,则必须在实例方法和静态方法两个方面具有不同之处。
实现此目标的最佳方法是使IAspectProvider
创建正确的外观:
[PSerializable]
public class LogAttribute : MethodLevelAspect, IAspectProvider
{
public IEnumerable<AspectInstance> ProvideAspects(object targetElement)
{
if (targetElement is MethodBase method)
{
if (method.IsStatic)
yield return new AspectInstance(targetElement, new StaticLogAspect());
else
yield return new AspectInstance(targetElement, new InstanceLogAspect());
}
}
}
[PSerializable]
internal abstract class BaseLogAspect : IAspect
{
[OnMethodEntryAdvice]
[SelfPointcut]
public virtual void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Base");
}
}
[PSerializable]
internal class StaticLogAspect : BaseLogAspect
{
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Static");
}
}
[PSerializable]
internal class InstanceLogAspect : BaseLogAspect, IInstanceScopedAspect
{
public object CreateInstance(AdviceArgs adviceArgs)
{
return new InstanceLogAspect();
}
public void RuntimeInitializeInstance()
{
}
public override void OnEntry(MethodExecutionArgs args)
{
Console.WriteLine("Instance");
}
}
注意IInstanceScopedAspect
导致为目标类的每个实例分配一个方面的对象。当您在方法上使用此方法时,此类方面可能会导致对象的内存占用量显着增加。
如果您的建议方法中需要与实例相关的信息,则最好在类型上使用一个“中心”实例作用域。该方面存储实例信息,并将接口引入目标类。然后,方法级方面将使用引入的接口来获取有关实例的信息。