2010-05-02 2 views
0

J'ai posé cette question dans les scripts NHibernate mais je pense que c'est plutôt une question générale. NHibernate utilise des générateurs proxy (par exemple Castle) pour créer son proxy.Définir la classe de base ou la fonctionnalité de base d'un proxy dynamique (par exemple, Castle, LinFu)

Ce que je voudrais faire est d'étendre le proxy généré afin qu'il implémente un peu de mon propre comportement personnalisé (c'est-à-dire un comparateur). J'ai besoin parce que le comportement standard .NET suivant ne parvient pas à produire les résultats corrects:

//object AC is a concrete class 
collection.Contains(AC) = true 

//object AP is a proxy with the SAME id and therefore represents the same instance as concrete AC 
collection.Contains(AP) = false 

Si mon comparateur a été mis en œuvre par AP (ne le match id) puis collection.Contains (AP) retournerait vrai, comme je Je m'attendrais à ce que les procurations soient implicites. (NB: Pour ceux qui disent que NH hérite de votre classe de base, oui, oui, mais NH peut aussi hériter d'une interface - ce que nous faisons)

Je ne suis pas du tout sûr que ce soit possible ou par où commencer. Est-ce quelque chose qui peut être fait dans l'un des générateurs de proxy communs que NH utilise?

Répondre

0

Ce genre de comportement est possible avec LinFu.DynamicProxy, mais vous devez remplacer l'intercepteur fourni par NHibernate avec votre propre intercepteur personnalisé que les délégués qu'il rappelle à l'intercepteur d'origine:

var yourProxiedInterfaceInstance = ... 

// Get the Interceptor that NHibernate uses 

var proxy = (IProxy)yourProxiedInterfaceInstance; 

var interceptor = proxy.Interceptor; 

// You'll need to create a decorator class around the IInterceptor interface 
var yourInterceptor = new SomeCustomInterceptor(interceptor); 

// Replace the interceptor here 
proxy.Interceptor = yourInterceptor; 

C'est assez facile à faire avec LinFu puisque chaque instance de proxy qu'il génère nécessite un intercepteur. Si vous modifiez l'intercepteur, vous pouvez modifier automatiquement le comportement d'un proxy. J'espère que ça aide.

+0

Merci pour le conseil. Au moins maintenant je sais ce que je veux n'est pas totalement hors du mur. Je vais regarder dans LinFu. – GrahamB

2

Avec Castle DynamicProxy, vous avez peu de choix.

La première consiste à fournir le IComparer<T> comme l'un des additionalInterfacesToProxy lors de la création du proxy. L'interface n'aura aucune implémentation réelle à effectuer, vous devez donc fournir un intercepteur qui au lieu d'appeler Proceed fournira la logique réelle pour les méthodes.

Vous pouvez également fournir un mixin, qui implémente l'interface requise et fournit la logique dont vous avez besoin. Notez que vous devrez probablement renvoyer la référence mixin au proxy ou à sa cible.

Troisième option, disponible uniquement pour les serveurs proxy d'interface est de définir la classe de base proxyGenerationOptions.BaseClassForInterfaceProxy = typeof(SomethingImplementingComparer);

+0

Krzysztof, la troisième option - je suppose que c'est un paramètre de château? Je ne peux pas le trouver dans la documentation de NH n'importe où. Il semble certainement être l'option la plus simple si je peux le brancher correctement. Je ne sais pas encore comment configurer Castle dans NH! – GrahamB

+0

oui, cela fait partie des paramètres de Castle. Pour câbler NHibernate, je pense que vous devrez fournir vos propres 'ProxyFactoryFactory' et' ProxyFactory'. Je commencerais par regarder ce qui est dans 'NHibernate.Bytecode.Castle.dll' –

+0

Krzysztof, est allé pour la troisième option, mais ça ne fonctionne pas comme je m'y attendais. Le proxy généré par le château est effectivement converti en la classe de base que j'ai spécifiée, mais il ne déclenche pas la comparaison de classe de base SAUF si je lance le proxy à la classe de base. Il semblerait que Castle «prêche» la classe de base, n'utilisant pas la classe de base comme proxy pour l'interface. Est-ce correct? – GrahamB

Questions connexes