好的,這可能會變得冗長。我想做兩件事:訂購Postharp方面執行
我想有一個類,實現一個接口,通過持有每個呼叫路由到另一個類的實例。
我也想攔截所有方法調用並做一些事情。
對自己的作品都做得很好。將它們結合起來似乎只能在一個執行順序中工作,而墨菲就是這樣做的,這是錯誤的(至少對我而言)。
我想注入合成第一個,這樣所有調用的攔截也將攔截先前注入的那些。
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
這顯然是行不通的。你有線索爲什麼我的執行順序沒有改變?我做錯了什麼,我錯過了文檔中的細節嗎?我能做些什麼來攔截我的注入組合物的方法?
您還需要添加'InterceptAspect'的'TestImpl'類來實現你想要的結果。 – nemesv
@nemesv雖然這可能會起作用,但TestImpl類有時並不是我的課程。我更喜歡一種解決方案,我可以將TestImpl保持原樣。 – nvoigt
另外,你可以在'ITest'接口上放置'[InterceptAspect(AttributeInheritance = MulticastInheritance.Multicast)]'。但這是你能得到的最遠的東西。問題是Postsharp在一步之內執行IL,並且它只對編譯時出現的方法應用'InterceptAspect',所以它看不到使用'ComposeAspect'添加的新接口實現。因此,使用'ComposeAspect'添加的類型應該已經包含'InterceptAspect'提供的日誌代碼,並將它放在'ITest'或'TestImpl'類上。 – nemesv