Bonjour Nico.
Quelle surprise ! Quelqu'un a utilisé le forum ! Vous êtes donc le premier à le faire. (Et comme personne ne l'utilisait, nous avions fini par nous lasser, et nous ne venions plus si souvent, désolé pour le délai d'attente).
Tout d'abord merci pour les compliments ! çà nous fait très plaisir :-)
Le problème que vous soulevez est relativement complexe, en effet, pour réaliser un DSL bidirectionnel, il faut réaliser :
- Un générateur de code incrémental
- Un rétro-ingénierie du code vers le modèle.
Pour ce qui est du générateur de code, du fait qu'il doit être incrémental, vous ne pouvez pas utiliser les templates T4 (puisque le code généré est systématiquement écrasé). Il vaut donc mieux, par exemple avec des règles ou des événements du Store pour synchroniser les modifications de votre modèle, avec l'arbre syntaxique de votre code. Pour ce qui est de l'arbre syntaxique du code, vous savez peut-être que, Visual Studio propose par exemple une namespace EnvDTE (ainsi que sa version 2005 EnvDTE80) qui permet la manipulation du code par une API (le CodeModel contient des CodeNamespace, qui contiennent des CodeNamespace et des CodeType, lesquels contiennent des CodeFunction, des CodeVariable, etc ...)
Pour ce qui est de la rétro-ingénierie, c'est pareil, une des manières de faire est de lire les informations à partir du CodeModel. Par contre, le faire en tirant l'information (pulling, par exemple chaque fois que votre modèle ou ses propriétés s'affichent) est à la fois peu performant et génant (car un code modifié par l'utilisateur peut, à certains moments ne pas compiler - c'est normal - et donc l'accès au CodeModel peut retourner des exceptions). C'est pourquoi il vaut mieux s'abonner aux CodeModelEvents, mais çà ... c'est compliqué également, car c'est très bas niveau
Voilà pour le principe. Cela suppose que vous sachiez accéder au CodeModel du projet dans lequel se trouve votre modèle, ce qui n'est pas très compliqué et fera l'objet d'un post très bientôt.
Alors pour le concret, je vais vous donner un scoop : nous sommes, en ce moment, en train d'écrire une bibliothèque de classes qui s'appelera Dslfactory.utilities, et qui vous permettra d'envisager ces scénario et bien d'autres. Je peux vous dire qu'elle est utilisée depuis peu dans un DSL en production et contient pour le moment deux classes principales :
- IncrementalGenerator qui permet de s'assurer qu'une classe existe dans un fichier et une namespace donnée, et si ce n'est pas le cas de la créer, etc pour les méthodes, classes encapsulées, attributs, propriétés, champs, etc ...
- KnownCodeTypes qui est une encapsultation d'un abonnement aux CodeModelEvents pour le projet (très délicat). Elle permet :
- d'itérer sur tous les types connus dans le projet (qu'ils soient dans le projet ou dans les assemblages référencés)
- d'être notifé quand des événements de haut niveau surviennent (classe créée / supprimée / modifiée - quand je dis modifiée, c'est par exemple devenue static, ou partial etc ...- méthode, champ, classe encapulée, propriété, etc ... créés / supprimés / modifiée.
A partir de ces deux classes vous pourrez alors relativement simplement créer un DSL bidirectionnel.
J'espère que cela répond à votre question.
A mon tour de vous en poser une : quelle est votre échéance ?
Jean-Marc