6
votes

Comment écrire une classe de convertisseur? Comment écrire efficacement les règles de cartographie?

J'ai une classe A assez grande avec beaucoup de membres, et j'ai une assez grande classe B qui peut être construit lors d'un objet d'un objet. Un objet peut être construit lors de la un objet B. J'ai besoin à la fois d'entre eux, comme c'est une sorte de viewmodel, qui a une validation et B est une description graphique qui peut être complotée facilement.

Comment faire cette conversion? p>

Voici un exemple, pour illustrer ce que je veux faire: p>

 "Y**D***RR****---***---***"


9 commentaires

Ayez juste une des classes hériter de l'autre.


Pensez que ce n'est pas le meilleur moyen, car on a la validation de l'entrée et de l'autre, malgré une complottement totalement différent, il est facile à parcourir, mais le contenu est similaire, mais mappé. Mais clairement, j'ai déjà pensé à avoir une classe de pono tenant les données et deux convertisseurs, entraînant un et un convertisseur pour a => pono et b => pono. Peut-être que c'est la voie à suivre.


C'est Poco, puisque c'est .net après tout :)


Bien sûr, vous avez raison! pensé de certains objets .net ...


Pouvez-vous donner un exemple de ce que "sculpter" de B ressemblerait?


Bien sûr, je vais éditerai dans la question


Pourrait-il être un ajustement pour le sérialisateur / désériorizer personnalisé? C'est-à-dire que les deux objet soient sérialisés / désérialisalisent un format commun ...


Bonne idée! Mais comment utiliser les règles de mappage de deux manières? Cela devrait peut-être être une autre question, alors ...


CODEPROJECT.COM/Articles/34118/LAMBDA-CONVERTER-PATTERN


5 Réponses :


3
votes

Y a-t-il des motifs bien connus pour atteindre cela?

Cela dépend de ce que vous entendez par motif. décorateur ou adaptateur schémas vous vient à l'esprit, mais cela ne signifie pas non plus la cartographie de gros de types à différents types.

Y a-t-il une manière C # par défaut de faire de telles choses?

Non, il n'y a pas. Mais les bibliothèques comme automapper sûr rendent la vie plus facile.


11 commentaires

+1, c'est essentiellement quelque chose que j'écris. Vraiment, vous envisagez de marquer votre classe avec un tas d'attributs afin que d'autres classes puissent l'inspecter avec réflexion et agir sur cette métadonnée.


@MAREINFINITUS - Ce n'est pas tout à fait clair ce que vous essayez d'accomplir, mais SURSPAPPER n'utilisera pas de chaîne pour vous. Un analyseur personnalisé ressemble à la meilleure option pour vous.


Ce que je veux savoir, c'est que, si vous construisez un tel analyseur personnalisé, existe-t-il des meilleures pratiques.


@Mareinfinit - pas que je sache. Utilisez le modèle d'état dans votre analyseur pour garder une trace de l'endroit où vous êtes et quelles transitions sont autorisées ( Le HTML Agilty Pack analyse HTML et est open source - un bon placé pour voir comment cela se fait).


Un schéma d'état semble être un moyen de suralimentation. Je ne vois pas pourquoi utiliser automapper avec des mappages personnalisés n'est pas la réponse ici. Vous pouvez écrire des expressions de Lamba pour définir vos règles «analyse».


@Ekoostikmartin - Je ne sais pas que je suis. D'après les commentaires de l'échantillon de code, je comprends que l'OP veut analyser une chaîne à un ensemble d'énumérations.


Je connais de l'automapper, mais je ne l'ai pas utilisé moi-même. Je vais en lire maintenant.


@ODed: C'est exactement ce qui est nécessaire pour le b => un cas.


@ODed - N'est-ce pas (String to Set d'Enums) juste une résolution de valeur personnalisée? github.com/automapper/automapper/wiki/custom-value-resolvers


@Ekoostikmartin - Je pense que vous êtes trop simplifié. L'exemple de l'OP impliqué 5 énumérations - Je ne sais pas que la création d'une résolution de valeur personnalisée serait plus facile qu'un analyseur personnalisé. Je peux me tromper. Ce n'est pas un aspect de la Fadifice que je connais très bien.


Les vraies classes sont un peu plus grandes. C'est un code hérité, mais une instance d'un objet B est quelque chose de plus de 4 kb (!) Lorsqu'il est correctement rempli.



0
votes

Factory + éventuellement façade

Vous voulez coordonner la construction d'un B de A A ou A A d'A B. Cela fait valoir que vous avez besoin de logique complexe pour le faire.

Pour construire B à partir d'un, outil de mise en oeuvre sous forme de méthode statique sur B (usine) ou créer une nouvelle classe C qui hérite de B, et prend une dispute à son constructeur (façade).

usine: http://fr.wikipedia.org/wiki/factory_method_pattern (pas un correspondance exacte pour votre situation)

Façade: http://fr.wikipedia.org/wiki/design_pattern_-_facade (pas une correspondance exacte non plus)


8 commentaires

Comme vous l'avez déjà indiqué, ces modèles de conception n'ont pas de correspondance exacte sur ce problème. Peut-être qu'il y a des meilleurs pratices pour C #.


Je pense que cette usine correspond bien. C'est juste que généralement l'usine est utilisée pour une construction beaucoup plus complexe, et la plupart des descriptions et des exemples rempliront donc cela. À mon avis, tout système où un A et A B est transmis à une méthode, puis configuez à volonté, sera qualifié de «usine», même si les instances sont construites ailleurs. Je pense toujours que la plupart des gens penseront à l'usine comme un "constructeur intelligent", et attendez donc que les instances soient construites à l'intérieur de l'usine.


L'usine ne résout qu'une petite partie du problème global, en particulier car il n'est pas possible de réutiliser les règles de cartographie.


Ensuite, je pense que vous recherchez peut-être "constructeur. Une classe spécifie la structure du produit, l'autre l'expression concrète de celui-ci. L'exemple habituel est une description abstraite d'un document (par exemple, en HTML) pouvant être rendue dans plusieurs Manières (bande formatage de la bande d'un texte uniquement, format comme HTML complet dans un navigateur, convertir en RTF ...)


Des modèles de conception unique vous indiquent rarement comment implémenter votre programme complet. Vous devrez généralement appliquer plusieurs. Ils sont vraiment assez tactiques quand cela revient. Dans ce cas, alors: Constructeur de spécifier la relation entre A et B, usine pour les créer et les configurer correctement pour interaction. Pour obtenir votre réutilisation des règles, demandez au constructeur de B à une compréhension et d'inverser une forme de constructeur A à B (ou inversement) EN.Wikipedia.org/wiki/Builder_Pattern


Merci pour vos commentaires! Comme mentionné précédemment, cette question n'est pas la recherche du bon mélange de modèles GOF. Je veux entendre parler des meilleures pratiques sur la cartographie des types différents, surtout s'ils sont aussi grands (comme mentionné, un objet de B est d'environ 4 Ko). L'application de différents ensembles de règles de mappage est ErrorPone et un travail de gain null. Mais je ne peux pas comprendre une solution C # claire pour cela pour cela pour cela, comme par exemple est assez simple en C ++ ... doit enquêter davantage à ce sujet.


Les modèles GOF sont une classe de meilleures pratiques. Je ne parle pas du modèle de constructeur parce que c'est gof. Je le mentionne parce que c'est la meilleure pratique lorsque vous souhaitez mapper une description (instance d'A ou B) à une façon de l'exprimer (instance de B ou A) avec les "mapper" comme des entités réutilisables, clairement délimitées. Je ne peux pas écrire votre code pour vous, car vous seul comprenez vraiment le problème. Je ne peux que vous conseiller sur la façon de l'organiser. Peut-être que si vous avez donné un exemple de la façon dont il est soi-disant facile en C ++?


Bien sûr, GOF est la meilleure pratique. Je les connais (et j'en ai utilisé la plupart d'entre eux quotidiennement), mais ici, j'ai besoin de quelque chose de différent, une nouvelle approche. Dans la cartographie C ++ est plus facile pour moi, car j'ai un fond lourd sur C ++ (12 ans de travail avec elle), mais seulement environ un an en C # 4.0



0
votes

Quelques pensées:

a) changer B dans une interface qui implémente. Cela vous permettrait de «mapper» les propriétés de B directement sur les propriétés de A sans avoir à les recréer. Dans les cas où B a une propriété qui n'est pas supposée avoir (ou une propriété qui combine plusieurs des A), vous pouvez définir le modificateur d'accès à privé * - ce qui signifie que la propriété ne sera visible que via l'interface (afin de ne pas le casse confondre ou encombrer les implémentations de A).

b) Utilisez un pseudo adaptateur / motif wrapper. B, étant donné un paramètre de constructeur de type A, peut renvoyer aux propriétés d'A, etc. Lorsque B diffère, il peut mettre en œuvre sa propre logique.

La cartographie entre deux objets complexes nécessite une réflexion complexe. Il y aura toujours des cas particuliers, des effets secondaires et des choix nécessitant une pensée et un équilibrage des avantages et des inconvénients. (Par exemple, la conversion entre une chaîne et une ST introduit toutes sortes de questions - que faire avec le séparateur des mille, comment gérer différentes cultures, etc.) de lire vos circonstances spécifiques, je ne vois pas de manière facile ou rapide de gérer la cartographie - vous aurez sur une méthode basée sur tous les facteurs impliqués, probablement trop nombreux pour poster ici.

EDIT: * Je dois noter que c'est ce que j'ai fait dans plusieurs projets VB. Je suppose que c'est légal en C #, mais je n'ai pas essayé.


3 commentaires

Je pense que je vais aller pour une DTO externe, qui sera utilisée à la fois par ces objets et que le mappage est effectué un <==> DTO <==> B. ressent le plus naturel pour le moment. Juste beaucoup de travail pour atteindre quelque chose de "assez simple".


Si c'était si simple, vous ne seriez probablement pas payé pour le faire. (Bien que, peut-être que vous n'êtes pas payé de toute façon!)


Il n'est pas simple d'une manière de l'écrire et tout est fait. La pièce de cartographie est toujours là;)



0
votes

Qu'est-ce que j'ai fait pour résoudre ce problème:

  1. a écrit un bimap (avec l'aide de SOS plus âgés sur cette question). P> li>

  2. inséra la mappage dans celle-ci (toutes les combinaisons de valeur dans la clé, la clé résultante de la "valeur", ainsi qu'un bitarray qui spécifie les indices de la chaîne qui sont défini par cette cartographie. p> li>

  3. a écrit un code pour calculer une chaîne globale résultante, comme la cartographie va juste donner des cordes partielles. p> li>

  4. Les mappages un-à-un étaient triviaux. P> li> ol>

    De cette façon, je pourrais utiliser les mappages des deux sens. Donné une chaîne, j'ai toujours un tout Recherche chère (comme je dois calculer la chaîne stockée en utilisant le bittarray comme masque) p>

    au moment où il semble fonctionner très bien, mais je n'ai pas encore fini. P>

    Merci à tous pour vos très bonnes idées et approches! Peut-être que Maquapper peut faire Cela, mais je n'ai pas beaucoup de temps pour le moment de lire et d'essayer une nouvelle technologie. P>

    Si quelqu'un peut fournir des exemples pertinents sur la manière de faire cela sur SURACHAPPER, Je l'accepterai comme une réponse (comme je l'aime déjà automapper). Strong> p>

    exemples comme permet de dire: 3 Enums avec 5 valeurs à une chaîne de longueur fixe Une chaîne de longueur fixe à 3 Enum avec 5 valeurs (l'inverse de ce qui précède). p>

    comme exemple: p>

    A.a && B.o && C.y ==> "**A**********************"
    A.a && B.p && C.y ==> "**B**********************"
    A.b && B.o && C.y ==> "*****X*******************"
    A.b && B.o && C.z ==> "*****W*******************"
    


0 commentaires

4
votes

Cela me semble que comme A est plus du modèle de données et B est plus du modèle de vue. Je ne pense pas qu'il y ait un "modèle" généralement accepté pour ce type d'instance, principalement parce que les raisons de ce type de couplage varient considérablement et le meilleur modèle dépend fortement de l'utilisation prévue.

Cela dit, car ils sont si étroitement liés ensemble, j'avais tendance à faire une classe subordonnée de classe à l'autre. Dans ce cas, étant donné que A est plus simple, j'utiliserais probablement un conteneur de données pour B. C'est-à-dire un membre privé A en tant que champ de classe B et toutes les propriétés de la classe B de catégorie de référence de catégorie B de catégorie de catégorie de mise à jour directe Un plutôt que d'avoir leurs propres champs privés derrière. Vous pourriez alors avoir une propriété publique sur la classe B qui expose le membre privé de la classe A si nécessaire. Je garderais probablement cette lecture seule, mais ce n'est probablement pas vraiment important (en fonction de votre utilisation de la classe B et de toutes les relations consolidées possibles). Pour aller dans l'autre moyen, je créerais ensuite un constructeur sur la classe B qui accepte la classe A comme paramètre. La valeur passée d'A serait alors attribuée à la classe privée d'un membre de la classe B.

Le résultat de tout ce qui est de maintenir l'ignorance de la classe A de la classe B - qui devient utile si vous avez un cas de véritable utilisation pour une situation de menu de vue. Si vous détermine que la classe A est la viet de la trajectoire de la route de vos besoins, puis inversez ce qui précède, de sorte que la classe B soit celle qui ignore la classe A.


2 commentaires

Merci! Oui, en effet, on se trouve près du Datamodel, tandis que l'autre est une sorte de menu de vue (pas dans le sens de MVVM, mais il peut être tracé directement). J'ai maintenant appliqué une solution, probablement pas le meilleur de tous, mais celle qui fonctionne et n'a pas trop de frais générale d'appliquer de nouveaux mappages et est facile à maintenir (avoir les mappages d'une ou B aura des frais généraux excessives, ayant deux endroits différents changer). Merci! +1


Chose sûre. Heureux que cela ait eu du sens. :)