后置方面执行的顺序
本文关键字:顺序 执行 方面 | 更新日期: 2023-09-27 18:09:47
好的,这可能会很长。我想做两件事:
-
我想有一个类,实现一个接口通过持有另一个类的实例,每个调用路由到。
-
我还想拦截所有的方法调用并做一些事情。
在自己的作品上做这两件事很棒。将它们结合起来似乎只能在一个执行顺序中工作,正如Murphy所说,这是错误的(至少对我来说)。
我想首先注入组合,这样所有调用的拦截也会拦截那些先前注入的调用。
namespace ConsoleApplication13
{
using System;
using System.Reflection;
using PostSharp;
using PostSharp.Aspects;
using PostSharp.Aspects.Dependencies;
using PostSharp.Extensibility;
[Serializable]
[ProvideAspectRole("COMPOSER")]
public sealed class ComposeAspectAttribute : CompositionAspect
{
[NonSerialized]
private readonly Type interfaceType;
private readonly Type implementationType;
public ComposeAspectAttribute(Type interfaceType, Type implementationType)
{
this.interfaceType = interfaceType;
this.implementationType = implementationType;
}
// Invoked at build time. We return the interface we want to implement.
protected override Type[] GetPublicInterfaces(Type targetType)
{
return new[] { this.interfaceType };
}
// Invoked at run time.
public override object CreateImplementationObject(AdviceArgs args)
{
return Activator.CreateInstance(this.implementationType);
}
}
[Serializable]
[ProvideAspectRole("INTERCEPTOR")]
[MulticastAttributeUsage(MulticastTargets.Method)]
[AspectRoleDependency(AspectDependencyAction.Order, AspectDependencyPosition.After, "COMPOSER")]
public sealed class InterceptAspectAttribute : MethodInterceptionAspect
{
public override void CompileTimeInitialize(MethodBase method, AspectInfo aspectInfo)
{
base.CompileTimeInitialize(method, aspectInfo);
// Warning in VS output
Message.Write(method, SeverityType.Warning, "XXX", "Method: " + method.Name);
}
public override void OnInvoke(MethodInterceptionArgs args)
{
Console.WriteLine("Intercepted before");
args.Proceed();
Console.WriteLine("Intercepted after");
}
}
interface ITest
{
void Call();
}
class TestImpl : ITest
{
public void Call()
{
Console.WriteLine("CALL remote implemented");
}
}
[InterceptAspect(AspectPriority = 1)]
[ComposeAspect(typeof(ITest), typeof(TestImpl), AspectPriority = 2)]
class Test
{
// this should, after compilation, have all methods of ITest, implemented through an instance of TestImpl, which get intercepted before TestImpl is called
public void CallLocalImplementedTest()
{
Console.WriteLine("CALL local implemented");
}
}
class Program
{
static void Main()
{
var test = new Test();
ITest t = Post.Cast<Test, ITest>(test);
Console.WriteLine("TEST #1");
t.Call();
Console.WriteLine("TEST #2");
test.CallLocalImplementedTest();
Console.ReadLine();
}
}
}
我试图通过
来影响这两个方面的执行顺序AspectRoleDependency,使拦截器依赖于首先运行的编写器
AspectPriority,也使作曲器优先运行
因为测试总是产生
TEST #1
CALL remote implemented
TEST #2
Intercepted before
CALL local implemented
Intercepted after
它显然不起作用。你知道为什么我的执行命令没有改变吗?是我做错了什么,还是我错过了文档中的某个细节?如何拦截组合注入的方法呢?
以目前的情况和你目前的设置,你无法达到你想要的结果。
问题在于Postsharp是如何工作的:它在一步中完成IL波,并且它只将InterceptAspect
应用于在原始编译时存在的方法,因此它看不到ComposeAspect
添加的新接口实现。
所以没有接受或提供角色,优先级或其他配置的顺序在这里有帮助。
一种解决方法是在注入的TestImpl
类上添加InterceptAspect
:
[InterceptAspect]
class TestImpl : ITest
{
public void Call()
{
Console.WriteLine("CALL remote implemented");
}
}
在这种情况下,日志逻辑将直接添加到TestImpl
中,所以这些方法将包含日志记录,当它将被组合到你的Test
类中。
或者如果你不标记每个实现,你可以把你的方面放在接口本身:
[InterceptAspect(AttributeInheritance = MulticastInheritance.Multicast)]
interface ITest
{
void Call();
}