Как работает OnMethodBoundaryAspect? - PullRequest
4 голосов
/ 24 марта 2012

Я обнаружил атрибут OnMethodBoundaryAspect в библиотеке PostSharp . Он может перехватывать вход и выход из метода следующим образом:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Method, Inheritance = MulticastInheritance.Multicast)]
public class InterceptAttribute : OnMethodBoundaryAspect
{
    public override void OnEntry(MethodExecutionArgs args)
    { }

    public override void OnExit(MethodExecutionArgs args)
    { }
}

public class A
{
    [Intercept]
    public void foo() { }
}

И мой вопрос "Как это работает?" Что я должен сделать, чтобы написать свой собственный атрибут, который сможет перехватывать вход и выход из метода (без PostSharp с использованием ofcourse)?

1 Ответ

9 голосов
/ 24 марта 2012

Прежде всего, я бы рекомендовал прочитать следующую документацию для внутренней работы (разделы "как это работает" и другие). По сути, атрибуты преобразуются в соответствующий код во время сборки (фактически, в основном после сборки, но все еще во время сборки). Существует понятие MSBuild task , которое указывает код, который будет запускаться во время процесса сборки. Код выполняется после завершения компиляции и ищет определенные атрибуты (например, InterceptAttribute) и может вносить изменения в скомпилированный код. Редактирование кода во время выполнения может быть выполнено при использовании библиотеки Mono.Cecil (она позволяет вводить / удалять код IL). Еще раз уточним:

  1. Код построен с присвоенными атрибутами.
  2. Во время сборки для каждой BuildTasks вызывается определенный код
  3. BuildTasks используют отражение, чтобы найти фрагменты кода, содержащие необходимые атрибуты
  4. BuildTasks используют Mono.Cecil для динамического внедрения кода в найденные фрагменты
  5. Сборка завершена. Ваша скомпилированная dll теперь содержит не только написанный код, но и атрибуты, измененные в некоторый код. Я бы посоветовал взглянуть на сборку с ILSpy или подобными декомпиляторами, чтобы увидеть разницу между вашим исходным кодом и сгенерированным.

Я бы рекомендовал просмотреть KindOfMagic кодов, чтобы увидеть, как автоматический RaisePropertyChanged из INotifyPropertyChanged реализован как атрибут. Он дает ценную информацию о создании пользовательских аспектов, хотя может оказаться сложным и утомительным процессом.

...