Ok, das kann lang werden. Ich versuche, zwei Dinge zu tun:Bestellung von Postsharp Aspekte Ausführung
Ich möchte eine Klasse haben, die eine Schnittstelle implementiert durch eine Instanz einer anderen Klasse halten, dass jeder Anruf wird weitergeleitet.
Ich möchte auch alle Methodenaufrufe abfangen und etwas tun.
Doing sowohl auf eigene Faust funktioniert super. Sie zu kombinieren, scheint nur in einer Ausführungsreihenfolge zu funktionieren und wie Murphy es hat, ist es das falsche (zumindest für mich).
Ich möchte die Zusammensetzung zuerst injizieren, so dass das Abfangen aller Anrufe auch jene abfangen wird, die zuvor injiziert wurden.
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();
}
}
}
Ich habe versucht, die Ausführungsreihenfolge der beiden Aspekte zu beeinflussen, indem
AspectRoleDependency, die Abfangjäger machen auf dem Komponisten abhängen ersten
AspectPriority, auch machen den Komponisten laufen Lauf zuerst.
Da die Tests ergeben immer
TEST #1
CALL remote implemented
TEST #2
Intercepted before
CALL local implemented
Intercepted after
es offensichtlich nicht funktioniert. Hast du eine Ahnung, warum sich meine Ausführungsreihenfolge nicht geändert hat? Habe ich etwas falsch gemacht, habe ich ein Detail in der Dokumentation vermisst? Was kann ich tun, um meine Kompositions-injizierten Methoden abzufangen?
Sie müssen auch den 'InterceptAspect' auf der' TestImpl' Klasse hinzufügen, um Ihr gewünschtes Ergebnis zu erzielen . – nemesv
@nemesv Obwohl das wahrscheinlich funktionieren würde, ist die TestImpl-Klasse manchmal nicht meine Klasse.Ich würde eine Lösung bevorzugen, wo ich TestImpl so lassen kann, wie es ist. – nvoigt
Alternativ können Sie Ihre '[InterceptAspect (AttributeInheritance = MulticastInheritance.Multicast)]' auf der 'ITest'-Schnittstelle selbst setzen. Aber das ist das weiteste, was du bekommen kannst. Das Problem ist, dass Postsharp die IL in einem Schritt winkt und nur die "InterceptAspect" auf die Methoden anwendet, die zur Kompilierzeit vorhanden sind, so dass die neuen Schnittstellenimplementierungen nicht mit dem "ComposeAspect" hinzugefügt werden. Daher sollte der Typ, den Sie mit dem ComposeAspect hinzufügen, bereits den Logging-Code enthalten, der von der InterceptAspect bereitgestellt wird, indem Sie ihn auf die ITest- oder die TestImpl-Klasse setzen. – nemesv