2015-10-26 1 views
0

Scénario:(Comment) Puis-je interroger les classes "post-build", en utilisant la réflexion en C# .Net?

  • J'ai une liste de fichiers .cs dans un projet studio visuel (par exemple, MyPOCOs), logeant un groupe de Poços (Plain Old C# objets)
  • Je dois exécuter une sérialisation personnalisée outil (de chez moi et j'ai accès au code source) qui convertit ces POCO en fichiers XML - l'outil le fait par réflexion.

Actuellement, le projet MyPOCOs est marqué comme une application console et a une principale méthode comme celle ci-dessous:

class Program 
    { 
     static void Main(string[] args) 
     { 
      //Initialize custom XML Serializer 
      GenerateBulkVmXML batchSerializer = new GenerateBulkVmXML(); 

      //Add individual POCOs to Serializer 
      batchSerializer.AddPocoModel(typeof(MyPOCO1), "My.Custom.NameSpace"); 
      batchSerializer.AddPocoModel(typeof(MyPOCO2), "My.Custom.NameSpace1"); 
      batchSerializer.AddPocoModel(typeof(MyPOCO3), "My.Custom.NameSpace2"); 

      //Generate custom XML 
      batchSerializer .WriteXML(); 
     } 
} 

Everytime we "run" l'application de la console ci-dessus, il déclenche la méthode Main , qui interroge les classes POCO par réflexion et crache le XML.

Problème: Pour chaque nouvelle POCO ajoutée au projet, nous avons ajouter une ligne à la méthode ci-dessus Main appelant la méthode batchSerializer.AddPocoModel(...) en passant leur type de Poco nouvellement créé. Au fil du temps, le nombre de POCO augmentera et cela deviendra plutôt lourd. Mon équipe suggère d'intégrer ce processus à la «construction» du projet MyPOCO, mais je ne suis pas sûr que tout le monde puisse saisir la viabilité de cette approche. Ainsi, lorsque nous 'construisons' le projet en studio visuel, la méthode Main ci-dessus est exécutée, essentiellement. Voici les deux problèmes que je vois cette approche:

  1. Comment puis-je découvrir les classes de sérialisation? Actuellement, je les ajoute à la méthode principale via la méthode AddPocoModel. Mais si je ne fais pas cela, comment puis-je les découvrir et les interroger par réflexion?
  2. Comment faire exactement je déclencheur post-construction principale méthode ci-dessus (il pourrait être une méthode dans une classe personnalisée. Je suis juste en utilisant le Main pour les besoins du raisonnement. En gros, comment puis-je déclencher la méthode qui fait ce que la méthode principale fait ci-dessus)?

Comment puis-je y parvenir? Ou, y a-t-il une meilleure solution au problème ci-dessus?

Répondre

2

Je voudrais sortir votre sérialiseur dans un projet distinct, une application console serait très bien. Cette application doit prendre un argument pointant vers la DLL qui vient d'être compilée, vous pouvez ensuite créer une commande post-construction qui exécute cet outil et transmet le nom de la DLL. Du côté positif, cela crée un outil réutilisable pour d'autres projets. Il y a un certain nombre de macros, mais le vôtre se retrouverait en regardant quelque chose comme:

"c:\path\to\serialization\tool.exe" $(TargetPath)

Quant à la découverte des types, car il n'y a probablement rien qui différencie vos classes de modèle POCO d'autres classes (s'il y a d'autres classes dans la DLL), vous devrez donc les marquer d'une manière ou d'une autre.Je vais avec un attribut personnalisé:

[AttributeUsage(AttributeTargets.Class, Inherited = false)] 
public class SerializePOCOAttribute : Attribute { } 

Ensuite, vous pouvez utiliser une méthode de découverte pour énumérer toutes les classes dans la DLL et les sérialisation, quelque chose comme:

public class POCOSerializer 
{ 
    public static void Serialize(string dllFileName, GenerateBulkVmXML batchSerializer) 
    { 
     var assem = Assembly.LoadFrom(dllFileName); 

     var pocoObjects = assem.GetTypes().Where(t => t.GetCustomAttribute<SerializePOCOAttribute>() != null); 

     foreach (var poco in pocoObjects) 
     { 
      batchSerializer.AddPocoModel(poco, poco.Namespace); 
     } 

     batchSerializer.WriteXML(); 
    } 
} 
+0

Je aime vraiment cette approche et Je suis enclin à aller avec ça. J'espère que * l'équipe de construction * ne tire pas vers le bas, puisque tous les projets sont actuellement * pas * des applications de console mais des bibliothèques de classes. Si l'application console n'est pas une option, avez-vous d'autres idées? Juste une pensée :) (PS: Actuellement les POCO * sont * annotés avec un attribut personnalisé, donc c'est un plus :) – PhD

+0

Le code arbitraire n'est vraiment pas "runnable" sans quelque chose pour le charger et l'exécuter. C'est essentiellement ce qui se passe lorsque vous créez un projet exe, le compilateur ajoute les points d'entrée et les sauts appropriés. Vous pouvez créer un outil qui exécute la méthode "main", mais vous ne pouvez pas simplement dire à l'action post-construction d'exécuter une méthode dans une DLL. J'aurais un gros problème avec une équipe de construction qui n'autorise pas une sorte d'outillage personnalisé, et [la nourriture pour chiens n'est pas une mauvaise chose] (https://en.wikipedia.org/wiki/Eating_your_own_dog_food). –

+0

Où exactement cet événement de post-construction sera écrit? Le fichier '.csproj' du projet pour lequel je veux déclencher l'outil? C'est mon lacune actuelle dans la compréhension de la mise en œuvre de cette approche - D'après ce que je comprends, vous parlez des événements pré/post build que vous pouvez configurer à l'aide de l'éditeur WYSIWYG de Visual Studio (Projet> Propriétés> Build Events)? – PhD