2009-08-29 6 views
6

Je voudrais être capable de décorer n'importe quelle méthode avec un attribut personnalisé Trace et un morceau de code devrait être injecté dans cette méthode lors de la compilation.Comment injecter du code C# au moment de la compilation?

Par exemple:

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

devrait devenir:

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

Dans ce cas, le code injecté dépend des paramètres de nom de la méthode et la méthode, il devrait donc être possible de déduire ces informations.

Est-ce que quelqu'un sait comment accomplir cela?

Répondre

13

Pour faire de la programmation orientée aspect en C#, vous pouvez utiliser PostSharp.

(The homepage montre même un Trace exemple, tout comme vous demandez!)

+0

Je n'ai jamais étudié les performances du code PostSharpened, mais je serais surpris si le cale PostSharp faisait une différence significative. – RichieHindle

+0

Je ne peux pas faire ce que je veux faire avec PostSharp Loas (plugin AOP pour PostSharp), mais je peux le faire en écrivant un plugin AOP personnalisé pour PostSharp. Alors que les Loas PostSharp peuvent avoir affecté les performances d'exécution, mon plugin personnalisé ne le sera pas puisque ce sera uniquement à la compilation. –

2

Cela peut se faire facilement avec un système de transformation du programme.

Le DMS Software Reengineering Toolkit est un système de transformation de programme à usage général, et peut être utilisé avec de nombreux langages (C++, COBOL, Java, EcmaScript, Fortran, ..) ainsi que spécifiquement avec C#. DMS analyse le code source, construit des arbres syntaxiques abstraits et vous permet d'appliquer des modèles source à source pour transformer votre code d'un programme C# en un autre avec les propriétés souhaitées. La règle de transformation pour accomplir exactement la tâche que vous avez spécifié serait:

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 } " 

Les guillemets (") ne sont pas les guillemets CSharp, mais plutôt, ils sont des « citations de domaine », et indiquent que le contenu à l'intérieur des guillemets est la syntaxe CSharp (parce que nous avons dit, « domaine CSharp »). les notations \ foo sont la syntaxe meta.

Cette règle correspond à l'AST représentant la méthode que vous avez spécifié avec l'annotation [Trace] et ré-écrit que AST en L'AST qui en résulte est alors réimprimé en forme de source, que vous pouvez compiler, vous avez probablement besoin d'autres règles pour gérer d'autres combinaisons d'arguments; act, vous généraliserez probablement le traitement des arguments pour produire (si possible) une valeur de chaîne pour chaque argument scalaire.

Il devrait être clair que vous pouvez faire beaucoup plus que simplement vous connecter avec ceci, et bien plus que de la programmation orientée aspect, puisque vous pouvez exprimer des transformations arbitraires et pas seulement des actions avant-après.

+0

Bien que cela semble très utile, je vais d'abord essayer PostSharp car c'est gratuit et l'accès à la source. Je serais également capable de renommer les attributs à tout moment et de ne rien casser. –

+0

Pourquoi semblez-vous objecter à cause du changement de nom? Si vous voulez renommer des attributs, vous pouvez également écrire une transformation de programme pour le faire également. –

Questions connexes