10
votes

Création d'une classe pour une interface au moment de l'exécution, en C #

Je cherche à prendre un ensemble d'objets, disons qu'il y a 3 objets en vie pour le moment, qui mettent en œuvre une interface commune, puis enveloppent ces objets à l'intérieur d'un quatrième objet, implémentant également la même interface.

Les implémentations des méthodes et des propriétés de quatrième objet appellent simplement les bits pertinents sur ces 3 objets sous-jacents. Je sais qu'il y aura des cas ici où il n'aura pas de sens de le faire, mais c'est pour une architecture de multidiffusion de service, il existe donc déjà un bon ensemble de limitations en place.

Ma question est de savoir où commencer. La génération de ce quatrième objet doit être effectuée en mémoire, au moment de l'exécution, je pense donc reflet.emit , malheureusement, je n'ai pas assez d'expérience avec cela pour savoir où commencer.

Dois-je construire un ensemble en mémoire? Il semble bien cela, mais j'aimerais juste qu'un pointeur rapide où je devrais commencer.

Fondamentalement, je cherche à prendre une interface et à la liste des instances d'objet qui mettent en œuvre cette interface et à la construction d'un nouvel objet, implémentant également cette interface, qui devrait "multidiffusion" tous les appels de méthode et l'accès à la propriété à tous les éléments sous-jacents. objets, au moins autant que possible. Il y aura des tas de problèmes avec des exceptions et aussi, mais je vais aborder ces bits lorsque je leur donne.

Ceci est pour une architecture axée sur les services, où j'aimerais disposer d'un code existant qui prend, comme exemple, un service d'enregistrement, pour accéder à plusieurs services d'enregistreurs multiples, sans avoir à modifier le code qui utilise les services. Au lieu de cela, j'aimerais pouvoir générer un wrapper d'enregistreur-service qui appelle simplement les méthodes pertinentes sur plusieurs objets sous-jacents.

Ceci est pour .NET 3.5 et C #.


4 commentaires

En fait, j'ai écrit un exemple qui a fait cela (ici à ce sujet) il y a quelques mois ... je vais voir si je peux le trouver ...


Ainsi? Stackoverflow.com/questions/847809/...


Marc, choisissez un moyen de résoudre ce problème, soit marquer la question en tant que duplicata, ou postez une vraie réponse que je peux accepter.


Et merci, au fait, cela ressemble exactement à ce dont j'ai besoin :)


3 Réponses :


1
votes

Avez-vous vraiment besoin de créer l'assemblage au moment de l'exécution?

Vous n'en avez probablement pas besoin.

C # vous donner une action , l'opérateur et la Lambda / Déléguats ...


2 commentaires

Le code d'un système du CIO, malheureusement, certaines des définitions de quels services invocants sont contenus dans des fichiers de configuration, qui peuvent être modifiés. Donc, j'ai vraiment besoin que cela soit à l'exécution, oui.


J'ai déjà fait quelque chose comme ça avant, passant le service qui sera appelé dans la configuration, car même si vous injecte l'objet à l'exécution, vous connaissez déjà l'interface qu'ils étendent. N'oubliez pas que vous pouvez passer des méthodes à votre classe et invoquer ce passage d'objets à invoquer ...



6
votes

(Je justifie une réponse ici en ajoutant un contexte / info supplémentaire)

Oui, au moment où reflet.emit est le seul moyen de résoudre ce problème.

in .NET 4.0, la classe Expression a été étendue à la prise en charge des blocs de boucles et de relevé, donc pour Méthode unique Utilisation, une expression compilée serait une bonne idée. Mais même cela ne prendra pas en charge les interfaces multi-méthodes (juste des délégués à la méthode unique).

Heureusement, j'ai déjà fait cela; Voir Comment puis-je écrire une classe de conteneurs générique qui implémente une interface donnée en C #?


0 commentaires

7
votes

Je posterai ma propre mise en œuvre ici, si quelqu'un est intéressé.

Ceci est fortement influencé et copié de la réponse de Marc, que j'ai accepté.

Le code peut être utilisé pour envelopper un ensemble de Objets, tous implémentant une interface commune, à l'intérieur d'un nouvel objet, implémentant également ladite interface. Lorsque des méthodes et des propriétés de l'objet retourné sont accessies, les méthodes et les propriétés correspondantes sur les objets sous-jacents sont accessibles de la même manière.

ici il y a des dragons : Ceci est pour un utilisation spécifique. Il existe un potentiel de problèmes impairs, en particulier depuis que le code ne garantit pas que tous les objets sous-jacents reçoivent les mêmes objets que la callee passe (ou plutôt, il n'interdit pas l'un des objets sous-jacents de jouer avec les arguments) et pour des méthodes qui renvoient une valeur, seule la dernière valeur de retour sera renvoyée. En ce qui concerne les arguments OUT / REF, je n'ai même pas testé ce que cela fonctionne, mais ce n'est probablement pas. vous avez été prévenu. xxx


1 commentaires

Quelle est cette "séquences.repeat" appelle fait? Et où est la classe "séquences"? BTW, merci pour cette réponse géniale!