2009-09-11 10 views
3

J'utilise Castle Windsor dans mon projet. Certains composants enregistrés sont interceptés. Parce que les composants sont enregistrés via des interfaces, Castle Windsor crée des proxies d'interface (Castle Windsor crée un type autonome qui implémente l'interface et délègue à l'implémentation réelle en utilisant la composition). Malheureusement, vous ne pouvez pas exécuter de méthodes dans l'implémentation réelle de l'interface, car le proxy serait contourné.Castle Windsor: Comment récupérer un proxy pour une instance spécifique?

Existe-t-il un moyen d'obtenir l'instance du proxy qui représente l'implémentation réelle dans l'implémentation réelle?

Voici un exemple de ce que je voudrais réaliser. Je veux toujours intercepter la méthode Get. S'il vous plaît ne venez pas avec d'autres moyens de refactoriser cet échantillon parce que ce n'est pas mon code de production, mais juste quelque chose inventé pour la démonstration.

public interface IProvider 
{ 
    bool IsEmpty { get; } 
    object Get(); 
} 

public class ProxyBypassingProvider : IProvider 
{ 
    public bool IsEmpty 
    { 
     // Calls method directly, not through the proxy. 
     get { return Get() == null; } 
    } 

    public object Get() 
    { 
     return new Object(); 
    } 
} 

public class InterceptedProvider : IProvider 
{ 
    private IProvider _this; // Should hold the proxy instance. 

    public bool IsEmpty 
    { 
     // Calls method through proxy. 
     get { return _this.Get() == null; } 
    } 

    public object Get() 
    { 
     return new Object(); 
    } 
} 

Comment puis-je définir le champ _this à l'instance du proxy?

Cordialement
Oliver Hanappi

PS: Voici un exemple du monde réel.

public interface IPresentationModel 
{ 
    IView View { get; } 
} 

public interface IView 
{ 
    void SetModel(IPresentationModel model); 
} 

public PresentationModel : IPresentationModel 
{ 
    public IView View { get; private set; } 

    public PresentationModel(IView view) 
    { 
     View = view; 
     View.SetModel(this); 
    } 
} 

Je résous un modèle de présentation transitoire. Il obtient une vue transitoire injectée. Étant donné que la vue doit connaître le modèle de présentation, le modèle de présentation appelle IView.SetModel (this) pour informer la vue sur son modèle de présentation.
Le problème est maintenant, que bien que le IPresentationModel résolu est un proxy, la méthode SetModel obtient seulement l'implémentation réelle. Par conséquent, lorsque la vue appelle des méthodes sur le modèle de présentation, aucun intercepteur n'est déclenché.

La seule solution que j'ai trouvée jusqu'à maintenant, est de définir manuellement le modèle de présentation de la vue après avoir résolu mon modèle de présentation.

var model = _container.Resolve<IPresentationModel>(); 
model.View.SetModel(model); 

Je pense que cette solution n'est pas vraiment très bien résolue.

+0

Il semble que vous soyez trop compliqué mais je ne suis pas sûr car je ne comprends pas très bien ce que vous essayez de réaliser ... Pourriez-vous poster plus de détails sur votre problème sous-jacent? –

+0

Salut! Je ne pense pas, je suis en train de compliquer les choses. Je veux juste utiliser des intercepteurs. Lorsqu'un objet résout IProvider, il n'obtient pas une instance du composant enregistré mais une instance d'une classe créée dynamiquement qui implémente IProvider. Cette classe transmet chaque requête à l'implémentation réelle, mais intercepte la requête. Lorsque l'implémentation réelle appelle une méthode d'interface, l'appel ne passe pas par le proxy créé dynamiquement, mais directement par la méthode réelle. Par conséquent, aucun intercepteur ne sera appelé. Hope, c'est maintenant un peu plus clair;) –

Répondre

3

Ceci est ce que l'on appelle un problème de "fuite", et il n'y a pas de bonne façon de résoudre ce problème pour les proxys d'interface. Il est probable que l'étape de post-composition que vous avez mentionnée serait la meilleure solution. Vous pouvez utiliser le OnCreateFacility de Tuna - il est intégré dans le tronc, ou si vous ne voulez pas utiliser le tronc, vous pouvez copier le code du référentiel et l'utiliser avec v2.0.

+0

Je pense, c'est trop compliqué à expliquer, pourquoi j'ai besoin de ça. Pourrions-nous simplement nous concentrer sur la question? –

+0

Ok, en se concentrant sur la question - vous ne pouvez pas. Mais encore une fois, quelle serait la raison de faire ce que vous faites?Si vous ne voulez pas en parler publiquement, envoyez-moi un email. Je suis vraiment curieux. –

+0

J'ai édité ma question et posté un exemple du monde réel. –

Questions connexes