3
votes

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
It looks like you're overcomplicating things but I'm not sure since I don't fully understand what you're trying to achieve... Could you post more details about your underlying issue?Mauricio Scheffer
Hi! I don't think, I'm making things more complication. I just want to use interceptors. When some object resolves IProvider, it does not get an instance of the registered component but instead an instance of an dynamically created class which implements IProvider. This class forwards every request to the real implementation, but intercepts the request. When the real implementation calls an interface method, the call won't go through the dynamically created proxy, but directly to the real method. Therefore no interceptor will be called. Hope, it is now a little bit more clear ;)Oliver Hanappi

1 Answers

3
votes

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.