Hi Krzysztof

Thanks for that. I just changed the code and it seems to be working :)

Thanks heaps

Patrick

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

>  Patrick,
>
> Thanks for the explanation. I think definately base type is the way to go.
>
>  HTH,
> Krzysztof
>
>
> On 14/05/2011 10:50 AM, Patrick van der Velde wrote:
>
> 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.
>
>
>  --
> 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