1

I am trying to understand Castle's DynamicProxy and the thing I would like to do is to change the target of the generated proxy at runtime.

Something like this...

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;

namespace ConsoleApplication16
{
    class Program
    {
        static void Main(string[] args)
        {
            IFoo foo = new Foo("Foo 1");

            IFoo foo2 = new Foo("Foo 2");

            foo.DoSomething("Hello!");

            ProxyGenerator generator = new ProxyGenerator();
            IFoo proxiedFoo = generator.CreateInterfaceProxyWithTarget<IFoo>(foo);

            proxiedFoo.DoSomething("Hello proxied!");

            (proxiedFoo as IChangeProxyTarget).ChangeProxyTarget(foo2); // cast results in null reference

            proxiedFoo.DoSomething("Hello!");
        }
    }
}

I thought the generated proxy would implement IChangeProxyTarget but the cast to the interface results in a null reference.

How can I change the target of a generated proxy at runtime?

Update As mentioned in an answer, I tried using CreateInterfaceProxyWithTargetInterface and I'm still unable to cast to IChangeProxyTarget to change the target.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Castle.DynamicProxy;

namespace ConsoleApplication16
{
    class Program
    {
        static void Main(string[] args)
        {
            IFoo foo = new Foo("Foo 1");

            IFoo foo2 = new Foo("Foo 2");

            foo.DoSomething("Hello!");

            ProxyGenerator generator = new ProxyGenerator();
            IFoo proxiedFoo = generator.CreateInterfaceProxyWithTargetInterface<IFoo>(foo);

            proxiedFoo.DoSomething("Hello proxied!");

            IChangeProxyTarget changeProxyTarget = proxiedFoo as IChangeProxyTarget;

            if (changeProxyTarget == null) // always null...
            {
                Console.WriteLine("Failed");
                return;
            }

            changeProxyTarget.ChangeProxyTarget(foo2);

            proxiedFoo.DoSomething("Hello!");
        }
    }
}
Jim
  • 4,910
  • 4
  • 32
  • 50
  • So what problem are you actually trying to solve? – Krzysztof Kozmic Aug 01 '13 at 22:02
  • My use case is that I have a generic service host caching WCF callback channels. The service host doesn't know what type of service contract it is caching. I want to create proxies to the actual callback so that I can control access and lifetime of the callback channel given a multi-threaded environment. Being able to swap out the target on demand would allow me to do that. I have done this with my own classes derived from RealProxy. With RealProxy you can get the underlying proxy class and invoke methods on it like I want to do with Castle. – Jim Aug 02 '13 at 13:27
  • 1
    To the person who downvoted, please explain what I can do to improve the question. – Jim Dec 31 '14 at 16:24

1 Answers1

1

use CreateInterfaceProxyWithTargetInterface

That one will allow you to change the proxy/invocation target.

Also the IChangeProxyTarget is implemented by invocation type, not the proxy itself.

Krzysztof Kozmic
  • 27,267
  • 12
  • 73
  • 115
  • I tried that and the proxy still is unable to be cast to the IChangeProxyTarget IChangeProxyTarget changeProxyTarget = proxiedFoo as IChangeProxyTarget; if (changeProxyTarget == null) // always null... { Console.WriteLine("Failed"); return; } – Jim Jul 31 '13 at 15:10
  • So there really is no way to change the target outside of adding an interceptor and changing thru the invocation object... – Jim Aug 01 '13 at 17:24
  • The whole point of a proxy is that it's transparent. The code using it doesn't know it's using a proxy. Hence it won't go trying fiddling with it. – Krzysztof Kozmic Aug 01 '13 at 22:01
  • Right, I want other developers who use the base service host to not know that I am controlling the lifetime and target of WCF callbacks behind the proxy. However, as the service host caching callbacks, my base service class does want to be able to fiddle with it. I'm trying to create a transparent developer experience to control cached WCF callback channels so the developers don't need to worry about managing it themselves, all they have to do is get a callback channel out of the cache (which I want to wrap in a proxy). – Jim Aug 02 '13 at 13:31
  • Because it seems apparent that DynamicProxy cannot do what I would like it to do, I am going to mark this one as the answer for "Also the IChangeProxyTarget is implemented by invocation type, not the proxy itself." – Jim Aug 07 '13 at 13:11
  • how can I change the `target` for **all** invocation? the docs says that when changing the target in the interceptor, it only changes for that particular method, but how can I change for all other methods? – JobaDiniz Mar 31 '20 at 15:36