2017-01-24 5 views
1

Моего аспекта:PostSharp - Применение аспекта mscorlib, но запретить изменение вызовов в моем собственном классе

[Serializable] 
class DumbLogger : OnMethodBoundaryAspect 
{ 
    public override void OnEntry(MethodExecutionArgs args) 
    { 
     Log.Print("Entry: ") + args.Method.Name; 
     args.FlowBehavior = FlowBehavior.Continue; 
    } 
} 

Это то, что я использую, чтобы изменить вызовы в mscorlib и пытаюсь исключить их от изменения в моем классе называется LOG

[assembly: MY_PROJECT.DumbLogger(
    AttributeTargetTypes = "MY_PROJECT.Log", 
    AttributeExclude = true, 
    AttributePriority = 1)] 


    [assembly: MY_PROJECT.DumbLogger(
    AttributeTargetAssemblies = "mscorlib", 
    AttributePriority = 2)] 

Но .. Это не делает трюк, потому что если я смотрю на мой LOG класса с ILspy декомпилятором я могу увидеть вызовы методов любого класса @ mscorlib.dll вносятся изменения, например:

<>z__Aspects.<System.Object.ToString>b__v(text) 

Причина, по которой я хочу сделать это, потому что, когда я вхожу в метод Log.Print, он генерирует исключение stackoverflow и будет бесконечно называть себя.

Я уже знаю, возможно, исключая определенные пространства имен и классы, такие как строка из mscorlib, но у меня есть причины сделать это так, как я описал.

ответ

0

Аспекты PostSharp в целом применяются к объявлениям (сборкам, типам, методам, параметрам, полям и т. Д.). Когда вы применяете MethodLevelAspect (базовый класс OnMethodBoundaryAspect) по внешнему методу, PostSharp преобразует сайт вызова (call инструкция в IL), но все же думает об аспект как о самом объявлении.

В настоящее время нет способа фильтровать по сайту вызова, и для этого потребуется другой вид аспект и/или советы. Поэтому ваш атрибут AttributeExclude=true на сборке не имеет никакого эффекта, поскольку он говорит, что этот аспект не должен применяться к типу Log, которого нет.

Общий метод, который решает именно этот случай использовать ThreadStatic переменного, чтобы разорвать порочные рекурсии, как следующий код демонстрирует:

[Serializable] 
class DumbLogger : OnMethodBoundaryAspect 
{ 
    [ThreadStatic] private static bool logging; 

    public override void OnEntry(MethodExecutionArgs args) 
    { 
     if (logging) 
      return; 

     try 
     { 
      logging = true; 
      Log.Print("Entry: " + args.Method.Name); 
      args.FlowBehavior = FlowBehavior.Continue; 
     } 
     finally 
     { 
      logging = false; 
     } 
    } 
} 

Пожалуйста, обратите внимание, что MethodInterception и OnMethodBoundary аспектов являются единственным аспектом, работа на внешних узлах.

+1

Спасибо Даниэлю, это работает, я получил этот ответ некоторое время назад (на самом деле не связанный с вопросом), но я подумал, что существует менее «обходной путь» иш ... –

+0

@JoaoVitor В настоящее время другого выхода нет. Это может измениться в будущем, но у нас нет никаких планов на что-то вроде «CallSiteLevelAspect», поскольку количество вариантов использования невозможно без него, кажется, совсем мало. –

Смежные вопросы