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