views:

252

answers:

1

Hi!

I'm using Castle Windsor in my project. Some registered components are intercepted. Because the components are registered through interfaces, Castle Windsor creates interface proxies (Castle Windsor creates a standalone type which implements the interface and delegates to the real implementation by using composition). Unfortunately you cannot execute methods within the real implementation of the interface, because the proxy would be bypassed.

Is there a way to get the instance of the proxy which represents the real implementation within the real implementation?

Here is an example of what I would like to achieve. I want to intercept always the Get method. Please don't come with alternative ways to refactor this sample because this is not my production code but just something invented for demonstration.

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();
    }
}

How can I set the field _this to the instance of the proxy?

Best Regards
Oliver Hanappi

PS: Here is a real world example.

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);
    }
}

I'm resolving a transient presentation model. It gets a transient view injected. Because the view needs to know about the presentation model, the presentation model calls IView.SetModel(this) to let the view know about its presentation model.
The problem is now, that although the resolved IPresentationModel is a proxy, the SetModel method gets only the real implementation. Therefore, when the view calls methods on the presentation model, no interceptors are being fired.

The only solution I have found until now, is to set the view's presentation model manually after I have resolved my presentation model.

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

I think, this solution is not really solved very well.

+1  A: 

This is so called "leaking this" problem, and there's no good way of solving this for interface proxies.

Probably the post-composition step you mentioned would be the best solution. You can use Tuna's OnCreateFacility - it's baked into the trunk, or if you don't want to run on the trunk, you can copy the code from the repository and use it with v2.0.

Krzysztof Koźmic
I think, it's too complicated to explain, why I need this. Could we just concetrate on the question?
Oliver Hanappi
Ok, concentrating on the question - you can't. But again, what would be the reason to do what you do? If you don't want to talk about it publicly, drop me an email. I'm genuinely curious.
Krzysztof Koźmic
I've editied my question and posted a real world example.
Oliver Hanappi
Ah, that could help me probably. Can I somehow intercept the resolving or proxying process of castle windsor?
Oliver Hanappi
You mean this: http://tunatoksoz.com/post/Implementing-EnrichWith%28of-StructureMap%29-with-Castle.aspx (it is only in the trunk unfortunately... it was added after the v2.0 release).
Krzysztof Koźmic
Thank you for your help, I've found an acceptable solution: I've written a small facitility which subscribes to the ComponentCreated event. I defined an interface which has a property for the Proxy instance and an initialization method. If the created component implements the interface, the proxy or the component itself will be assigned to the property and the initialize method will be invoked right after.
Oliver Hanappi
I like that solution. Not maybe having implement additional interface part - I'd rather use a naming convention here, but ComponentCreated is a good place for this. +1
Krzysztof Koźmic