Как внедрить код C # во время компиляции? - PullRequest
7 голосов
/ 30 августа 2009

Я хотел бы иметь возможность украсить любой метод с помощью пользовательского атрибута Trace, и при компиляции в этот метод должен быть вставлен некоторый фрагмент кода.

Например:

[Trace]
public void TracedMethod(string param1)
{
   //method body
}

должно стать:

public void TracedMethod(string param1)
{
   Log.Trace("TracedMethod", "param1", param1);
   //method body
}

В этом случае введенный код зависит от имени метода и параметров метода, поэтому должна быть возможность вывести эту информацию.

Кто-нибудь знает, как этого добиться?

Ответы [ 2 ]

13 голосов
/ 30 августа 2009

Чтобы выполнить аспектно-ориентированное программирование в C #, вы можете использовать PostSharp .

( На домашней странице даже показан пример Trace, как вы и просили!)

2 голосов
/ 31 августа 2009

Это легко сделать с помощью системы преобразования программ.

DMS Software Reengineering Toolkit - это система преобразования программ общего назначения, которая может использоваться со многими языками (C ++, COBOL, Java, EcmaScript, Fortran, ..), а также, в частности, с C #.

DMS анализирует исходный код, создает деревья абстрактного синтаксиса и позволяет применять шаблоны от источника к источнику для преобразования кода из одной программы на C # в другую с любыми желаемыми свойствами. Правило преобразования для точного выполнения указанной вами задачи:

domain CSharp.

insert_trace():method->method
  "[Trace]
   \visibility \returntype \methodname(string \parametername)
   { \body  } "
      ->
  "\visibility \returntype \methodname(string \parametername)
   { Log.Trace(\CSharpString\(\methodname\),
               \CSharpString\(\parametername\),
               \parametername);
      \body } "

Кавычки (") не являются кавычками CSharp, скорее они являются" доменными кавычками "и указывают, что содержимое внутри кавычек является синтаксисом CSharp (потому что мы сказали" domain CSharp "). The \ foo нотации являются мета-синтаксисом.

Это правило сопоставляет AST, представляющий указанный вами метод с аннотацией [Trace], и ​​переписывает этот AST в отслеживаемую форму. Полученный AST затем печатается обратно в исходную форму, которую вы можете скомпилировать. Вам, вероятно, нужны другие правила для обработки других комбинаций аргументов; на самом деле, вы, вероятно, обобщите обработку аргументов, чтобы получить (где это практически возможно) строковое значение для каждого скалярного аргумента.

Должно быть ясно, что вы можете делать намного больше, чем просто регистрировать с этим, и намного больше, чем просто аспектно-ориентированное программирование, поскольку вы можете выражать произвольные преобразования, а не только действия до и после.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...