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.
