Permalink
Browse files

Make ServiceRunner + NServiceExec work with MQ Requests

  • Loading branch information...
1 parent 811b5fe commit 33106aeb5ab4f5171b4dded09c58c4ebd1fa8793 @mythz mythz committed Oct 3, 2012
Showing with 353 additions and 351 deletions.
  1. +166 −164 src/ServiceStack/ServiceHost/NServiceExec.cs
  2. +187 −187 src/ServiceStack/ServiceHost/ServiceRunner.cs
@@ -1,165 +1,167 @@
-using System;
-using System.Collections.Generic;
-using System.Linq.Expressions;
-using System.Reflection;
-using ServiceStack.ServiceClient.Web;
-using ServiceStack.Text;
-using ServiceStack.WebHost.Endpoints;
-
-namespace ServiceStack.ServiceHost
-{
- public interface INServiceExec
- {
- object Execute(IRequestContext requestContext, object instance, object request);
- }
-
- public class NServiceRequestExec<TService, TRequest> : INServiceExec
- {
- static NServiceRequestExec()
- {
- NServiceExec<TService>.CreateServiceRunnersFor<TRequest>();
- }
-
- public object Execute(IRequestContext requestContext, object instance, object request)
- {
- return NServiceExec<TService>.Execute(requestContext, instance, request,
- typeof(TRequest).Name);
- }
- }
-
- public class NServiceExec<TService>
- {
- private static Dictionary<Type, List<ActionContext>> actionMap
- = new Dictionary<Type, List<ActionContext>>();
-
- private static Dictionary<string, InstanceExecFn> execMap
- = new Dictionary<string, InstanceExecFn>();
-
- static NServiceExec()
- {
- var mis = typeof(TService).GetMethods(BindingFlags.Public | BindingFlags.Instance);
- foreach (var methodInfo in mis)
- {
- var mi = methodInfo;
- if (mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void)) continue;
- var args = mi.GetParameters();
- if (args.Length != 1) continue;
- var actionName = mi.Name.ToUpper();
- if (!HttpMethod.AllVerbs.Contains(actionName) && actionName != ActionContext.AnyAction)
- continue;
-
- var requestType = args[0].ParameterType;
- var actionCtx = new ActionContext {
- Id = ActionContext.Key(actionName, requestType.Name),
- RequestType = requestType,
- };
-
- try
- {
- actionCtx.ServiceAction = CreateExecFn(requestType, mi);
- }
- catch
- {
- //Potential problems with MONO, using reflection for fallback
- actionCtx.ServiceAction = (service, request) =>
- mi.Invoke(service, new[] { request });
- }
-
- var reqFilters = new List<IHasRequestFilter>();
- var resFilters = new List<IHasResponseFilter>();
-
- foreach (var attr in mi.GetCustomAttributes(false))
- {
- var hasReqFilter = attr as IHasRequestFilter;
- var hasResFilter = attr as IHasResponseFilter;
-
- if (hasReqFilter != null)
- reqFilters.Add(hasReqFilter);
-
- if (hasResFilter != null)
- resFilters.Add(hasResFilter);
- }
-
- if (reqFilters.Count > 0)
- actionCtx.RequestFilters = reqFilters.ToArray();
-
- if (resFilters.Count > 0)
- actionCtx.ResponseFilters = resFilters.ToArray();
-
- if (!actionMap.ContainsKey(requestType))
- actionMap[requestType] = new List<ActionContext>();
-
- actionMap[requestType].Add(actionCtx);
- }
- }
-
- public static ActionInvokerFn CreateExecFn(Type requestType, MethodInfo mi)
- {
- var serviceType = typeof(TService);
-
- var serviceParam = Expression.Parameter(typeof(object), "serviceObj");
- var serviceStrong = Expression.Convert(serviceParam, serviceType);
-
- var requestDtoParam = Expression.Parameter(typeof(object), "requestDto");
- var requestDtoStrong = Expression.Convert(requestDtoParam, requestType);
-
- Expression callExecute = Expression.Call(
- serviceStrong, mi, requestDtoStrong);
-
- if (mi.ReturnType != typeof(void))
- {
- var executeFunc = Expression.Lambda<ActionInvokerFn>
- (callExecute, serviceParam, requestDtoParam).Compile();
-
- return executeFunc;
- }
- else
- {
- var executeFunc = Expression.Lambda<VoidActionInvokerFn>
- (callExecute, serviceParam, requestDtoParam).Compile();
-
- return (service, request) => {
- executeFunc(service, request);
- return null;
- };
- }
- }
-
- public static List<ActionContext> GetActionsFor<TRequest>()
- {
- List<ActionContext> requestActions;
- return actionMap.TryGetValue(typeof(TRequest), out requestActions)
- ? requestActions
- : new List<ActionContext>();
- }
-
- public static void CreateServiceRunnersFor<TRequest>()
- {
- foreach (var actionCtx in GetActionsFor<TRequest>())
- {
- if (execMap.ContainsKey(actionCtx.Id)) continue;
-
- var serviceRunner = EndpointHost.CreateServiceRunner<TRequest>(actionCtx);
- execMap[actionCtx.Id] = serviceRunner.Process;
- }
- }
-
- public static object Execute(IRequestContext requestContext,
- object instance, object request, string requestName)
- {
- var actionName = requestContext.Get<IHttpRequest>().HttpMethod;
-
- InstanceExecFn action;
- if (execMap.TryGetValue(ActionContext.Key(actionName, requestName), out action)
- || execMap.TryGetValue(ActionContext.AnyKey(requestName), out action))
- {
- return action(requestContext, instance, request);
- }
-
- var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLower();
- throw new NotImplementedException(
- "Could not find method named {1}({0}) or Any({0}) on Service {2}"
- .Fmt(request.GetType().Name, expectedMethodName, typeof(TService).Name));
- }
- }
+using System;
+using System.Collections.Generic;
+using System.Linq.Expressions;
+using System.Reflection;
+using ServiceStack.ServiceClient.Web;
+using ServiceStack.Text;
+using ServiceStack.WebHost.Endpoints;
+
+namespace ServiceStack.ServiceHost
+{
+ public interface INServiceExec
+ {
+ object Execute(IRequestContext requestContext, object instance, object request);
+ }
+
+ public class NServiceRequestExec<TService, TRequest> : INServiceExec
+ {
+ static NServiceRequestExec()
+ {
+ NServiceExec<TService>.CreateServiceRunnersFor<TRequest>();
+ }
+
+ public object Execute(IRequestContext requestContext, object instance, object request)
+ {
+ return NServiceExec<TService>.Execute(requestContext, instance, request,
+ typeof(TRequest).Name);
+ }
+ }
+
+ public class NServiceExec<TService>
+ {
+ private static Dictionary<Type, List<ActionContext>> actionMap
+ = new Dictionary<Type, List<ActionContext>>();
+
+ private static Dictionary<string, InstanceExecFn> execMap
+ = new Dictionary<string, InstanceExecFn>();
+
+ static NServiceExec()
+ {
+ var mis = typeof(TService).GetMethods(BindingFlags.Public | BindingFlags.Instance);
+ foreach (var methodInfo in mis)
+ {
+ var mi = methodInfo;
+ if (mi.ReturnType != typeof(object) && mi.ReturnType != typeof(void)) continue;
+ var args = mi.GetParameters();
+ if (args.Length != 1) continue;
+ var actionName = mi.Name.ToUpper();
+ if (!HttpMethod.AllVerbs.Contains(actionName) && actionName != ActionContext.AnyAction)
+ continue;
+
+ var requestType = args[0].ParameterType;
+ var actionCtx = new ActionContext {
+ Id = ActionContext.Key(actionName, requestType.Name),
+ RequestType = requestType,
+ };
+
+ try
+ {
+ actionCtx.ServiceAction = CreateExecFn(requestType, mi);
+ }
+ catch
+ {
+ //Potential problems with MONO, using reflection for fallback
+ actionCtx.ServiceAction = (service, request) =>
+ mi.Invoke(service, new[] { request });
+ }
+
+ var reqFilters = new List<IHasRequestFilter>();
+ var resFilters = new List<IHasResponseFilter>();
+
+ foreach (var attr in mi.GetCustomAttributes(false))
+ {
+ var hasReqFilter = attr as IHasRequestFilter;
+ var hasResFilter = attr as IHasResponseFilter;
+
+ if (hasReqFilter != null)
+ reqFilters.Add(hasReqFilter);
+
+ if (hasResFilter != null)
+ resFilters.Add(hasResFilter);
+ }
+
+ if (reqFilters.Count > 0)
+ actionCtx.RequestFilters = reqFilters.ToArray();
+
+ if (resFilters.Count > 0)
+ actionCtx.ResponseFilters = resFilters.ToArray();
+
+ if (!actionMap.ContainsKey(requestType))
+ actionMap[requestType] = new List<ActionContext>();
+
+ actionMap[requestType].Add(actionCtx);
+ }
+ }
+
+ public static ActionInvokerFn CreateExecFn(Type requestType, MethodInfo mi)
+ {
+ var serviceType = typeof(TService);
+
+ var serviceParam = Expression.Parameter(typeof(object), "serviceObj");
+ var serviceStrong = Expression.Convert(serviceParam, serviceType);
+
+ var requestDtoParam = Expression.Parameter(typeof(object), "requestDto");
+ var requestDtoStrong = Expression.Convert(requestDtoParam, requestType);
+
+ Expression callExecute = Expression.Call(
+ serviceStrong, mi, requestDtoStrong);
+
+ if (mi.ReturnType != typeof(void))
+ {
+ var executeFunc = Expression.Lambda<ActionInvokerFn>
+ (callExecute, serviceParam, requestDtoParam).Compile();
+
+ return executeFunc;
+ }
+ else
+ {
+ var executeFunc = Expression.Lambda<VoidActionInvokerFn>
+ (callExecute, serviceParam, requestDtoParam).Compile();
+
+ return (service, request) => {
+ executeFunc(service, request);
+ return null;
+ };
+ }
+ }
+
+ public static List<ActionContext> GetActionsFor<TRequest>()
+ {
+ List<ActionContext> requestActions;
+ return actionMap.TryGetValue(typeof(TRequest), out requestActions)
+ ? requestActions
+ : new List<ActionContext>();
+ }
+
+ public static void CreateServiceRunnersFor<TRequest>()
+ {
+ foreach (var actionCtx in GetActionsFor<TRequest>())
+ {
+ if (execMap.ContainsKey(actionCtx.Id)) continue;
+
+ var serviceRunner = EndpointHost.CreateServiceRunner<TRequest>(actionCtx);
+ execMap[actionCtx.Id] = serviceRunner.Process;
+ }
+ }
+
+ public static object Execute(IRequestContext requestContext,
+ object instance, object request, string requestName)
+ {
+ var actionName = requestContext != null
+ ? requestContext.Get<IHttpRequest>().HttpMethod
+ : HttpMethod.Post; //MQ Services
+
+ InstanceExecFn action;
+ if (execMap.TryGetValue(ActionContext.Key(actionName, requestName), out action)
+ || execMap.TryGetValue(ActionContext.AnyKey(requestName), out action))
+ {
+ return action(requestContext, instance, request);
+ }
+
+ var expectedMethodName = actionName.Substring(0, 1) + actionName.Substring(1).ToLower();
+ throw new NotImplementedException(
+ "Could not find method named {1}({0}) or Any({0}) on Service {2}"
+ .Fmt(request.GetType().Name, expectedMethodName, typeof(TService).Name));
+ }
+ }
}
Oops, something went wrong. Retry.

0 comments on commit 33106ae

Please sign in to comment.