Making DynamicProxy Interceptor's Intercept method an async method

1,939 views
Skip to first unread message

Kristijan Horvat

unread,
Jul 16, 2013, 10:39:26 AM7/16/13
to castle-pro...@googlegroups.com
Hi,

  are you planing to implement async support to DynamicProxy Interceptor's Intercept method ?

Thanks

Krzysztof Kozmic

unread,
Jul 16, 2013, 5:08:51 PM7/16/13
to castle-pro...@googlegroups.com
Hey,

What specifically beyond what's already possible did you have in mind?

@K

-- 
Krzysztof Kozmic

--
You received this message because you are subscribed to the Google Groups "Castle Project Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to castle-project-u...@googlegroups.com.
To post to this group, send email to castle-pro...@googlegroups.com.
Visit this group at http://groups.google.com/group/castle-project-users.
For more options, visit https://groups.google.com/groups/opt_out.
 
 

Kristijan Private

unread,
Jul 16, 2013, 6:14:49 PM7/16/13
to castle-pro...@googlegroups.com, Krzysztof Kozmic
Hi,

Intercept & Invocation Proceed methods aren't async therefore not awaitable. I have explained this in more detail on StackOverflow Ninject Interception and async. I can post a link if you can find it.

Regards

-- Sent from my Android phone with K-@ Mail. Please excuse my brevity.

Kristijan Horvat

unread,
Jul 17, 2013, 3:45:54 AM7/17/13
to castle-pro...@googlegroups.com

Mauricio Scheffer

unread,
Jul 18, 2013, 1:02:29 AM7/18/13
to castle-pro...@googlegroups.com
Not sure I understand completely what you're trying to do, but can't you just do something like this?

    internal class Program {
        private static void Main(string[] args) {
            var generator = new ProxyGenerator();
            var c = generator.CreateClassProxy<AsyncClass>(new AsyncInterceptor());
            var x = c.GetSomething().Result;
            Console.WriteLine(x);
        }
    }

    public class AsyncClass {
        public virtual async Task<string> GetSomething() {
            var h = new HttpClient();
            var response = await h.GetAsync("http://www.google.com");
            var content = await response.Content.ReadAsStringAsync();
            return content;
        }
    }

    public class AsyncInterceptor : IInterceptor {
        public async void Intercept(IInvocation invocation) {
            invocation.Proceed();
            var result = await (Task<string>)invocation.ReturnValue;
            invocation.ReturnValue = Task.Factory.StartNew(async () => {
                var h = new HttpClient();
                var response = await h.GetAsync("http://www.bing.com");
                var content = await response.Content.ReadAsStringAsync();
                return content + result;
            });
        }
    }

Cheers



--
Mauricio


Kristijan Horvat

unread,
Jul 18, 2013, 3:24:57 AM7/18/13
to castle-pro...@googlegroups.com
Let me show you the Castle.Core generated code so you can see the exact point where async is missing

// Castle.Proxies.IMyServiceProxy
public virtual Task<boolGetResult()
{
    IMyService arg_19_0 = null;
    IInterceptor[] arg_19_2 = this.__interceptors;
    MethodInfo arg_19_3 = IMyServiceProxy.token_GetResult;
    object[] array = new object[0];
    IMyService_GetResult myService_GetResult = new IMyService_GetResult(arg_19_0, this, arg_19_2, arg_19_3, array);
    myService_GetResult.Proceed();
    return (Task<bool>)myService_GetResult.get_ReturnValue();
}

I'm not sure if I mentioned that I have an async call just before you call "invocation.Proceed();" and that is manifesting as described below.

This line "myService_GetResult.Proceed();" is causing an issue because this method calls interceptor's Intercept method and inside that method you have an async method awaiting for result. But then control is returned back to caller which is "myService_GetResult.Proceed();" and it's not awaiting, next line will require a Task<bool> to be returned but get_ReturnValue() is null. The rest of your code seems fine.

Let me know if you have any ideas how to overcome this ?

Thanks

Mauricio Scheffer

unread,
Jul 18, 2013, 9:39:46 AM7/18/13
to castle-pro...@googlegroups.com
Can you please post a stand-alone program or stick to my example? Otherwise you're making things unnecessarily hard for others to see and diagnose your problem.

--
Mauricio

Kristijan Horvat

unread,
Jul 19, 2013, 5:22:31 AM7/19/13
to castle-pro...@googlegroups.com
Ok, np I have a BeforeInvoke method that I need to await so my code looks more like this:

 public class AsyncInterceptor : IInterceptor {
        public async void Intercept(IInvocation invocation) {
            await BeforeInvoke();
            invocation.Proceed();
            var result = await (Task<string>)invocation.ReturnValue;
            invocation.ReturnValue = Task.Factory.StartNew(async () => {
                var h = new HttpClient();
                var response = await h.GetAsync("http://www.bing.com");
                var content = await response.Content.ReadAsStringAsync();
                return content + result;
            });
        }
    }

At that "await BeforeInvoke();" point control is passed back to caller and that is the proxy method that I have provided you with and in your case it would be translated to something similar to this:

    IAsyncClass_GetSomething asyncClass_GetSomething = new IAsyncClass_GetSomething(arg_19_0, this, arg_19_2, arg_19_3, array);
    asyncClass_GetSomething.Proceed();

Well Proceed is not awaited and then control is passed one level up, at that point you aren't waiting for result anymore. So problem is awaiting anything before "invocation.Proceed();" because proxy isn't generating async code. (http://stackoverflow.com/questions/17663808/making-ninject-interceptors-intercept-method-an-async-method - take a look at Stephen Cleary comment) I have inspected LinFu DynamicProxy and it seems that he is generating more acceptable code for this kind of scenario. I'm testing the code right now I can post the results as soon as I'm done.

Thanks

Mauricio Scheffer

unread,
Jul 20, 2013, 7:09:21 PM7/20/13
to castle-pro...@googlegroups.com
Ah, I see what you mean now. Have you considered using a higher-order function (or a decorator) instead of a proxy?



--
Mauricio


--

Kristijan Private

unread,
Jul 21, 2013, 5:17:18 AM7/21/13
to castle-pro...@googlegroups.com
I have to use Castle.Core or LinFu with Ninject, I don't have time to implement custom interception.

BTW I think that I have get this up and running by changing Ninject implementation and using LinFu.

Thanks for your help

Rich Private

unread,
Mar 14, 2016, 3:44:45 PM3/14/16
to Castle Project Users
Mauricio,

Are there any updates as to whether or not DynamicProxy will support "async Task Intercept" ?


On Saturday, July 20, 2013 at 6:09:21 PM UTC-5, Mauricio Scheffer wrote:
Ah, I see what you mean now. Have you considered using a higher-order function (or a decorator) instead of a proxy?



--
Mauricio


On Fri, Jul 19, 2013 at 6:22 AM, Kristijan Horvat <kho...@icodeteam.net> wrote:
Ok, np I have a BeforeInvoke method that I need to await so my code looks more like this:

 public class AsyncInterceptor : IInterceptor {
        public async void Intercept(IInvocation invocation) {
            await BeforeInvoke();
            invocation.Proceed();
            var result = await (Task<string>)invocation.ReturnValue;
            invocation.ReturnValue = Task.Factory.StartNew(async () => {
                var h = new HttpClient();
                var response = await h.GetAsync("http://www.bing.com");
                var content = await response.Content.ReadAsStringAsync();
                return content + result;
            });
        }
    }

At that "await BeforeInvoke();" point control is passed back to caller and that is the proxy method that I have provided you with and in your case it would be translated to something similar to this:

    IAsyncClass_GetSomething asyncClass_GetSomething = new IAsyncClass_GetSomething(arg_19_0, this, arg_19_2, arg_19_3, array);
    asyncClass_GetSomething.Proceed();

Well Proceed is not awaited and then control is passed one level up, at that point you aren't waiting for result anymore. So problem is awaiting anything before "invocation.Proceed();" because proxy isn't generating async code. (http://stackoverflow.com/questions/17663808/making-ninject-interceptors-intercept-method-an-async-method - take a look at Stephen Cleary comment) I have inspected LinFu DynamicProxy and it seems that he is generating more acceptable code for this kind of scenario. I'm testing the code right now I can post the results as soon as I'm done.

Thanks

--
You received this message because you are subscribed to the Google Groups "Castle Project Users" group.
To unsubscribe from this group and stop receiving emails from it, send an email to castle-project-users+unsub...@googlegroups.com.

hammett

unread,
Mar 14, 2016, 3:48:15 PM3/14/16
to castle-pro...@googlegroups.com
Task support isnt quite required. Just get the result of the method
call, and if it's a task, act accordingly (check for completion, add
continuation, etc)
>>> email to castle-project-u...@googlegroups.com.
>>> To post to this group, send email to castle-pro...@googlegroups.com.
>>> Visit this group at http://groups.google.com/group/castle-project-users.
>>> For more options, visit https://groups.google.com/groups/opt_out.
>>>
>>>
>>
>>
> --
> You received this message because you are subscribed to the Google Groups
> "Castle Project Users" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to castle-project-u...@googlegroups.com.
> To post to this group, send email to castle-pro...@googlegroups.com.
> Visit this group at https://groups.google.com/group/castle-project-users.
> For more options, visit https://groups.google.com/d/optout.



--
Cheers,
hammett
http://www.d-collab.com/
http://www.hammettblog.com/
Reply all
Reply to author
Forward
0 new messages