I have a pattern that looks like this when used with known, compile-time types:
// given a method like this...
public RSType ComputeSomething(RQType rq) {
RSType rs = new RSType();
// do something to rs here, based on rq...
return rs;
}
// I'm able to do create an event handler like this
eventHandlers.RequestResponseAsync<RQType, RSType>(rq =>
Task.Factory.StartNew(() =>
{
return ComputeSomething(rq);
}));
And now I'm trying to use reflection so that a function like ComputeSomething can be found at runtime, and then RequestResponseAsync invoked as appropriate.
There is a non-async version, and I've got that working. For example, given the same ComputeSomething:
// get the handler method, and types
var handlerType = Assembly.LoadFrom("SomeAssembly").GetType("SomeNameSpace.SomeClass");
var handlerMethod = handlerType.GetMethod("ComputeSomething");
var handlerParamType = handlerMethod.GetParameters().FirstOrDefault().ParameterType;
var handlerReturnType = handlerMethod.ReturnType;
// get MethodInfo for a generic RequestResponseAsync
var respond = eventHandlers.GetType().GetMethod("RequestResponseAsync");
var genericRespond = respond.MakeGenericMethod(new Type[] { handlerParamType, handlerReturnType });
// create a delegate to pass to the invocation
var delegateType = typeof(Func<,>).MakeGenericType(handlerParamType, handlerReturnType);
var del = Delegate.CreateDelegate(delegateType, handlerMethod);
// invoke the method
genericRespond.Invoke(eventHandlers, new[] { del });
But my brain is too small to figure out how to take it to the next, Async level.
Can someone show me?
I'm not sure if someone suggested this a possibility, but I wanted to close the loop.
Here's what I've done, which seems to work.
I've created a generic Func factory function which I then call via reflection.
Func<RQ,Task<RS>> RqRsAsyncHandler<RQ,RS>(Func<RQ,RS> handler)
{
return (RQ rq) =>
{
return Task.Factory.StartNew(() =>
{
return handler(rq);
});
};
}
Then, I basically proceed as before but, instead, pass in the Func created by the function factory.
// get a delegate for the actual handler
var delegateType = typeof(Func<,>).MakeGenericType(handlerParamType, handlerReturnType);
var del = Delegate.CreateDelegate(delegateType, handlerMethod);
// get a Func that wraps that handler in a tracer handler
var RqRsAsyncHandlerMethodInfo = typeof(Container).GetMethod("RqRsAsyncHandler");
var RqRsAsyncHandlerMethodInfoGeneric = RqRsAsyncHandlerMethodInfo.MakeGenericMethod(handlerParamType, handlerReturnType);
var wrapperFunc = RqRsAsyncHandlereMethodInfoGeneric.Invoke(null, new object[] { del });
// get the eventHandlers method
MethodInfo respondMethod = typeof(EventHandlers).GetMethod("RespondAsync");
MethodInfo genericRespondMethod = respondMethod.MakeGenericMethod(new[] { handlerParamType, handlerReturnType });
// invoke the Bus method
genericRespondMethod.Invoke(eventHandlers , new[] { wrapperFunc });
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.