7
votes

Définir couramment les propriétés C # et les méthodes de chaînage

J'utilise .NET 3.5. Nous avons des classes tierces complexes qui sont automatiquement générées et hors de mon contrôle, mais que nous devons travailler à des fins de test. Je vois que mon équipe fait beaucoup de biens profondément imbriqués, d'obtenir / de fixer notre code de test, et il devient assez encombrant.

Pour remédier au problème, je voudrais faire une interface fluide pour définir les propriétés sur les différents objets. dans l'arbre hiérarchique. Il existe un grand nombre de propriétés et de classes dans cette bibliothèque tierce, et il serait trop fastidieux de tout cartographier manuellement. P>

Ma pensée initiale était de simplement utiliser des initialisateurs d'objets. rouge code>, bleu code> et vert code> sont des propriétés et mix () code> est une méthode qui définit une quatrième propriété Couleur Code> à la couleur de sécurité RVB la plus proche avec cette couleur mélangée. Les peintures doivent être homogénéisées avec remous () code> avant qu'ils puissent être utilisés. P> xxx pré>

qui fonctionne pour initialiser le peinture code>, Mais j'ai besoin de chaîner mix () code> et d'autres méthodes à elle. Tentative suivante: p> xxx pré>

mais cela ne va pas bien, car je dois définir une méthode pour chaque propriété que je veux définir, et il y a des centaines de propriétés différentes dans toutes les classes. En outre, c # n'a pas de moyen de définir dynamiquement des méthodes avant c # 4, donc je ne pense pas que je puisse me connecter à des choses pour le faire automatiquement d'une manière ou d'une autre. P>

Troisième tentative: P >

Create<Bucket>(Create<Paint>().Set(p => {
    p.Red = 0.4;
    p.Blue = 0.2;
    p.Green = 0.1;
  }).Mix().Stir()
)


1 commentaires

En fait, j'ai une approche similaire dans l'un de mes projets.


4 Réponses :


9
votes

Est-ce que cela fonctionne?

Bucket b = new Bucket() {
  Paint = new Paint() {
    Red = 0.4;
    Blue = 0.2;
    Green = 0.1;
  }.Init(p => {
    p.Mix().Stir();
  })
};


3 commentaires

Dans Retrospect, cela semble être une approche évidente. Je dois manquer la forêt pour les arbres de regarder cela trop longtemps!


FYI pour ceux qui sont perplexes par @Chis : le @ signifie "Traitez le jeton suivant comme identifiant littéral" (pas comme mot clé). L'effet est de nommer un paramètre appelé ceci .


Je ne suis pas perplexe par cela, mais je ne vois aucune raison de combattre le compilateur ici lorsque vous pouvez utiliser un nom équivalent comme auto ou source . Sinon, bonne réponse et +1.



5
votes

Je penserais de cela de cette façon:

Vous voulez essentiellement que votre dernière méthode dans la chaîne retourne un seau. Dans votre cas, je pense que vous voulez que la méthode soit mélangée (), comme vous pouvez remuer () le godet après p> xxx pré>

de sorte que vous devez définir au moins une couleur avant vous appelez mix (). Forcons cela avec certaines interfaces de syntaxe. P> xxx pré>

et appliquons-les au godetBuilder p> xxx pré> p> Vous avez besoin d'une initiale Propriété statique pour lancer la chaîne p> xxx pré>

et c'est à peu près tout, vous avez maintenant une interface fluide avec les paramètres RVB en option (tant que vous entrez au moins une) en tant que Bonus. P>

CreateBucket.UsingPaint.Red(0.4).Green(0.2).Mix().Stir();


0 commentaires

0
votes

J'utiliserais la méthode d'extension init parce que vous pouvez toujours jouer avec le délégué. Enfer, vous pouvez toujours déclarer des méthodes d'extension qui prennent des expressions et jouent même avec les expresions (stockez-les pour plus tard, modifiez, peu importe) De cette façon, vous pouvez facilement stocker des grups par défaut comme: xxx

de cette façon, vous pouvez utiliser toutes les actions (ou Funcs) et mettre en cache des initialisateurs standard comme chaînes d'expression pour plus tard?


0 commentaires

0
votes

Si vous voulez vraiment pouvoir chaîner des paramètres de propriété sans avoir à écrire une tonne de code, une façon de le faire serait d'utiliser la génération de code (CODEDOM). Vous pouvez utiliser la réflexion pour obtenir une liste des propriétés mutables, générer une classe de constructeur fluide avec une méthode finale Build () code> qui renvoie la classe que vous essayez réellement de créer.

i ' m Vous allez sauter sur tous les trucs de la chaudière sur la façon d'enregistrer l'outil personnalisé - c'est assez facile à trouver la documentation sur mais toujours à long terme et je ne pense pas que je puisse ajouter grand chose en y compris. Je vais vous montrer ce que je pense pour le codegen cependant. P>

MyCompany.MyProject.Paint
MyCompany.MyProject.Foo
MyCompany.MyLibrary.Bar


0 commentaires