Hi Krzysztof

I forgot about that. There is another method on the CommandProxy class that
is used to raise the event. So the signature of the CommandProxy class
should be more like this:

public class CommandProxy : ICommands
    {
        public event EventHandler<EventArgs> OnTerminated;

        private void RaiseOnAvailabilityChange()
        {
            var local = OnTerminated;
            if (local != null)
            {
                local(SelfReference(), EventArgs.Empty);
            }
        }

        // Stop the leaking of the 'this' reference by getting it from this
method
        // The proxy will override this method and make sure we only return
the
        // link to the proxy.
        protected internal virtual object SelfReference()
        {
            return this;
        }

        public void NotifyOfTermination()
        {
            RaiseOnAvailabilityChange();
        }
    }

The NotifyOfTermination method is invoked when the remote interface
disappears (e.g. the remote application signs off from the network or
something). The method is called by casting the proxy to a commandproxy and
then invoking the method, e.g.:

            var generator = new ProxyGenerator();
            var proxy =
(ICoolCommands)generator.CreateInterfaceProxyWithTarget(
                typeof(ICoolCommands),
                baseObject,
                options,
                new IInterceptor[] { selfReference, methodWithoutResult,
methodWithResult });

            var commandProxy = (CommandProxy)proxy;
            commandProxy.NotifyOfTermination ();

I'll try out the BaseTypeForInterfaceProxies property and see where it gets
me. Would an other solution be to do the following?

            var generator = new ProxyGenerator();
            var proxy =
(ICoolCommands)generator.CreateInterfaceProxyWithTarget(
                typeof(ICommands),
                new Type[] { typeof(ICoolCommands) },
                baseObject,
                options,
                new IInterceptor[] { selfReference, methodWithoutResult,
methodWithResult });

I'm not sure what that would do with the overlapping events on the
ICoolCommands interface though.

Regards

Patrick

2011/5/14 Krzysztof Koźmic <[email protected]>

>  @Patrick,
>
> How and when is RaiseOnAvailabilityChange method invoked?
>
> I'm not sure I got that right but I think what you're really after is proxy
> without target, but instead with CommandProxy class as its base class.
>
> ProxyGenerationOptions has a BaseTypeForInterfaceProxies property for that.
>
> HTH,
> Krzysztof
>
>
> On 13/05/2011 8:00 AM, Patrick van der Velde wrote:
>
> Hi All
>
>  I'm trying to use DynamicProxy to create a proxy object for a remote
> interface. For that to work I've done the following. I have defined a base
> interface for all command interfaces. This base interface doesn't provide
> any command methods but does provide an event. The base interface looks like
> this:
>
>      public interface ICommands
>     {
>         event EventHandler<EventArgs> OnTerminated;
>     }
>
>  That base interface is implemented by a proxy base class which will be
> used to refer to the proxy in the storage layer. The definition of that base
> proxy object looks like:
>
>      public class CommandProxy : ICommands
>     {
>         public event EventHandler<EventArgs> OnTerminated;
>
>          private void RaiseOnAvailabilityChange()
>         {
>             var local = OnTerminated;
>             if (local != null)
>             {
>                 local(SelfReference(), EventArgs.Empty);
>             }
>         }
>
>          // Stop the leaking of the 'this' reference by getting it from
> this method
>         // The proxy will override this method and make sure we only return
> the
>         // link to the proxy.
>         protected internal virtual object SelfReference()
>         {
>             return this;
>         }
>     }
>
>  Interfaces that derive from ICommands are only allowed to have methods
> that either return Task or Task<T> to indicate that any method called on the
> interface is likely to take up a finite amount of time. An example
> definition of a command interface looks like this:
>
>      public interface ICoolCommands : ICommands
>     {
>         Task SomeMethod(int input);
>
>          Task<int> SomeOtherMethod(int input);
>      }
>
>  The actual definition of the command interfaces may be different and is
> not known to the proxy building code.
>
>  I've then defined several interceptors to handle the case of methods with
> a Task return value and methods with a Task<T> return value.
> The first interceptor handles (I think) the 'SelfRefence' method in the
> base proxy object.
>      internal sealed class CommandSetProxySelfReferenceInterceptor :
> IInterceptor
>     {
>         public void Intercept(IInvocation invocation)
>         {
>             invocation.ReturnValue = invocation.Proxy;
>         }
>     }
>
>  The following two interceptors handle the case of methods with a Task and
> a Task<T> return value. Note that these interceptors never call in to the
> proxy base object because that object doesn't have any of the correct
> methods implemented.
>     internal sealed class CommandSetMethodWithTaskResultInterceptor :
> IInterceptor
>     {
>         public void Intercept(IInvocation invocation)
>         {
>             invocation.ReturnValue =
>                 Task.Factory.StartNew(
>                     () => Console.WriteLine(
>                         string.Format("{}({})",
>                         invocation.Method.Name,
>                         invocation.Arguments[0])));
>         }
>     }
>
>      internal sealed class CommandSetMethodWithTypedTaskResultInterceptor
> : IInterceptor
>     {
>         public void Intercept(IInvocation invocation)
>         {
>             invocation.ReturnValue =
>                 Task<int>.Factory.StartNew(
>                     () =>
>                     {
>                         Console.WriteLine(
>                             string.Format("{}({})",
>                             invocation.Method.Name,
>                             invocation.Arguments[0]));
>                         return 10;
>                     });
>         }
>     }
>
>  And finally there is an interceptorselector to handle setting up the
> interceptor chains.
>
>      internal sealed class CommandSetInterceptorSelector :
> IInterceptorSelector
>     {
>         public IInterceptor[] SelectInterceptors(Type type, MethodInfo
> method, IInterceptor[] interceptors)
>         {
>             var name = "SelfReference";
>             if (string.Equals(name, method.Name, StringComparison.Ordinal))
>             {
>                 return interceptors.Where(i => i is
> CommandSetProxySelfReferenceInterceptor).ToArray();
>             }
>
>              if (method.ReturnType == typeof(Task))
>             {
>                 return interceptors.Where(i => i is
> CommandSetMethodWithTaskResultInterceptor).ToArray();
>             }
>
>              return interceptors.Where(i => i is
> CommandSetMethodWithTypedTaskResultInterceptor).ToArray();
>         }
>     }
>
>  Now to build the proxy I use the following code (simplified from the real
> code)
>
>      class Program
>      {
>         static void Main(string[] args)
>         {
>              var baseObject = new CommandProxy();
>
>              var selfReference = new
> CommandSetProxySelfReferenceInterceptor();
>             var methodWithoutResult = new
> CommandSetMethodWithTaskResultInterceptor();
>             var methodWithResult = new
> CommandSetMethodWithTypedTaskResultInterceptor();
>
>              var options = new ProxyGenerationOptions
>             {
>                 Selector = new CommandSetInterceptorSelector(),
>             };
>
>              var generator = new ProxyGenerator();
>             var proxy =
> (ICoolCommands)generator.CreateInterfaceProxyWithTarget(
>                 typeof(ICoolCommands),
>                 baseObject,
>                 options,
>                 new IInterceptor[] { selfReference, methodWithoutResult,
> methodWithResult });
>
>              proxy.SomeMethod(10);
>             var result = proxy.SomeOtherMethod(20);
>             Console.ReadLine();
>         }
>     }
>
>  The problem is that it fails when I try to create the proxy (the line
> that has generator.CreateInterfaceProxyWithTarget) because the target
> doesn't implement the ICoolCommands interface. So the question now is how
> can I:
> - Create a proxy for a derivative of the ICommands interface, without the
> proxy code knowing what that interface is going to be
> - Have a base object that I can use to invoke events on
>
>  I suspect I want some form of mixin (as shown here
> http://kozmic.pl/2009/08/12/castle-dynamic-proxy-tutorial-part-xiii-mix-in-this-mix)
> but I'm not sure about that. If anybody has any good suggestions then that
> would be awesome.
>
>  In case it's necessary I've attached a C# code file with the example
> code.
>
>  With kind regards
>
>  Patrick van der Velde
> --
> You received this message because you are subscribed to the Google Groups
> "Castle Project Users" group.
> To post to this group, send email to [email protected]
> .
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/castle-project-users?hl=en.
>
>
>  --
> You received this message because you are subscribed to the Google Groups
> "Castle Project Users" group.
> To post to this group, send email to [email protected]
> .
> To unsubscribe from this group, send email to
> [email protected].
> For more options, visit this group at
> http://groups.google.com/group/castle-project-users?hl=en.
>

-- 
You received this message because you are subscribed to the Google Groups 
"Castle Project Users" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/castle-project-users?hl=en.

Reply via email to