2017-05-30 2 views
1

Im Grunde, was ich will, ist:automatisch Methoden injizieren zu einer Klasse auf Kompilierung-

Wenn ich eine Klassendefinition wie diese:

public class MyClass() 
{ 
    public int MyMethod() 
    { 
     return 42; 
    } 
} 

ich eine andere Kopie aller injizieren will Methoden zur Kompilierzeit.

So ist die tatsächliche kompilierte Version würde (zum Beispiel) wie folgt aussehen:

public class MyClass() 
{ 
    public int MyMethod() 
    { 
     return 42; 
    } 

    // injected method ... 
    public int MyMethodInjected() 
    { 
     return MyMethod() * 2; // just an example 
    } 
} 

Ich weiß, dass dies möglich sein sollte, Postsharp mit einem Typ-Attribut, kann aber nicht herausfinden, wie es zu tun. Alle Aspektattribute, die ich betrachtet habe, modifizieren einfach die existierende Methode, was ich nicht will. Ich möchte für jede Methode eine neue injizierte Methode erstellen.

Antwort

2

Dies ist derzeit nicht mit PostSharp Aspect Framework möglich, da Sie die eingeführte Methode nicht benennen können. Als Referenz ist folgendes zu beachten:

[DuplicateAspect] 
public class TargetClass 
{ 
    public int MyMethod() 
    { 
     return 42; 
    } 
} 

// We want the aspect to apply to types and provide other aspects. 
[PSerializable] 
public class DuplicateAspect : TypeLevelAspect, IAspectProvider 
{ 
    public IEnumerable<AspectInstance> ProvideAspects(object targetElement) 
    { 
     Type targetType = (Type)targetElement; 

     foreach (MethodInfo method in targetType.GetMethods(BindingFlags.Public | BindingFlags.Instance | BindingFlags.DeclaredOnly)) 
     { 
      // For each public instance method declared in the target type, apply an aspect that duplicates a single method. 
      yield return new AspectInstance(targetType, new DuplicateSingle(method)); 
     } 
    } 
} 

// We want the aspect to be instance-scoped and provide advices. 
[PSerializable] 
public class DuplicateSingle : IAspect, IInstanceScopedAspect, IAdviceProvider 
{ 
    private MethodInfo sourceMethod; 
    public Func<int> Method; 

    public DuplicateSingle(MethodInfo sourceMethod) 
    { 
     this.sourceMethod = sourceMethod; 
    } 

    public IEnumerable<AdviceInstance> ProvideAdvices(object targetElement) 
    { 
     Type targetType = (Type)targetElement; 
     FieldInfo field = typeof(DuplicateSingle).GetField(nameof(Method)); 
     MethodInfo method = typeof(DuplicateSingle).GetMethod(nameof(IntroducedMethod)); 

     // Provide import method advices, which stores delegate into a field of the aspect upon instance creation (remember - instance scoped aspect). 
     yield return new ImportMethodAdviceInstance(field, this.sourceMethod.Name, false, ImportMemberOrder.BeforeIntroductions); 

     // Provide introduce method advice, which introduces a stub calling the aspect method into the target class. 
     // PROBLEM: It's not possible to rename the method, hence this will fail. 
     yield return new IntroduceMethodAdviceInstance(method, PostSharp.Reflection.Visibility.Public, false, MemberOverrideAction.Fail); 
    }  

    public object CreateInstance(AdviceArgs adviceArgs) 
    { 
     return new DuplicateSingle(this.sourceMethod); 
    } 

    public void RuntimeInitializeInstance() 
    { 
    } 

    public int IntroducedMethod() 
    { 
     return this.Method() * 2; 
    } 
} 

Das eingeführte Verfahren wird immer gleichen Namen werden als Methode Informationen, die Sie auf den Rat Instanz zur Verfügung stellen (es gibt derzeit keine Möglichkeit, die Einführung von Methodennamen zu ändern).

Da es keinen größeren Vorteil bietet, Methoden dynamisch einzuführen, glaube ich nicht, dass dies jemals als ein gültiger Anwendungsfall von PostSharp implementiert wäre.

Ich würde mehr Low-Level-IL-Umschreibe-Tools wie Mono CeCil vorschlagen.

+0

Vielen Dank für die Erklärung Daniel. – GregaMohorko

+0

@Daniel Balas, kannst du bitte etwas mehr erklären, was dein _reference code_ tut? –

+1

@AntonKrouglov Kommentare hinzugefügt, die zu dem Problem führen, das ich beschreibe. Ist es o.k? –

Verwandte Themen