No worries,

cheers.

On 14/05/2011 4:25 PM, Patrick van der Velde wrote:
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] <mailto:[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]
    <mailto:[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 <http://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 <http://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]
        <mailto:[email protected]>.
        To unsubscribe from this group, send email to
        [email protected]
        <mailto:[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]
        <mailto:[email protected]>.
        To unsubscribe from this group, send email to
        [email protected]
        <mailto:castle-project-users%[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]
    <mailto:[email protected]>.
    To unsubscribe from this group, send email to
    [email protected]
    <mailto:[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]
    <mailto:[email protected]>.
    To unsubscribe from this group, send email to
    [email protected]
    <mailto:castle-project-users%[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