public NetStitchMiddleware(RequestDelegate next, Assembly[] assemblies, NetStitchOption option) { server = new NetStitchServer(assemblies, option); if (!Servers.TryAdd(option.ServerID, server)) { throw new InvalidOperationException($"Duplicate Server ID : {option.ServerID}"); } }
public NetStitchServer(Assembly[] assemblies, NetStitchOption option) { this.Option = option; this.Option.Logger.ServerSetupStart(); var tm = System.Diagnostics.Stopwatch.StartNew(); var types = assemblies .SelectMany(x => { try { return(x.GetTypes()); } catch (ReflectionTypeLoadException ex) { return(ex.Types.Where(t => t != null)); } }); var seq = types .Where(x => x.GetInterfaces().Any(t => t == typeof(INetStitchContract))) .Select(x => { try { return(new { interfaceType = x, targetType = types.Where(t => t.GetInterfaces().Any(t2 => t2 == x)).SingleOrDefault() }); } catch (InvalidOperationException) { throw; } }) .Where(x => x.targetType != null) .Where(x => x.targetType.GetTypeInfo().IsAbstract == false) .Select(x => x.targetType.GetTypeInfo().GetRuntimeInterfaceMap(x.interfaceType)) .SelectMany( x => x.TargetMethods.Zip(x.InterfaceMethods, (targetMethod, interfaceMethod) => new { targetMethod, interfaceMethod }), (x, methods) => { return(new { x.TargetType, x.InterfaceType, methods.targetMethod, methods.interfaceMethod, }); }); foreach (var element in seq) { var op = new OperationController(element.TargetType, element.InterfaceType, element.targetMethod, element.interfaceMethod, option); OperationMap.Add(op.OperationID, op); } this.Option.Logger.ServerSetupCompleted(tm.Elapsed); }
public NetStitchMiddleware(RequestDelegate next, Type type, NetStitchOption option) : this(next, new[] { type.GetTypeInfo().Assembly }, option) { }
public static IApplicationBuilder UseNetStitch(this IApplicationBuilder builder, Assembly[] assemblies, NetStitchOption option) { return builder.UseMiddleware<NetStitchMiddleware>(assemblies, option); }
public static IApplicationBuilder UseNetStitch(this IApplicationBuilder builder, Type type, NetStitchOption option) { return builder.UseMiddleware<NetStitchMiddleware>(type, option); }
public OperationController(Type targetType, Type interfaceType, MethodInfo targetMethodInfo, MethodInfo interfaceMethodInfo, NetStitchOption option) { ParameterInfo[] parameterInfos = targetMethodInfo.GetParameters(); this.ClassType = targetType; this.InterfaceType = interfaceType; this.MethodInfo = targetMethodInfo; this.ParameterType = parameterInfos.Length == 0 ? null : parameterInfos.Length == 1 ? parameterInfos[0].ParameterType : CreateParameterSturctType(interfaceType, targetMethodInfo); this.OperationID = $"/{InterfaceType.Name}/{MethodInfo.Name}"; bool requiresOperationContext = targetType.GetInterfaces().Any(x => x == typeof(IOperationContext)); bool operationIsAsyncType = typeof(ValueTask <>).IsAssignableFrom(targetMethodInfo.ReturnType); bool operationIsAsyncFunction = operationIsAsyncType && targetMethodInfo.ReturnType.GenericTypeArguments.Length != 0; Type asyncRetunType = targetMethodInfo.ReturnType.GenericTypeArguments.FirstOrDefault(); // new Class() or new Class() { Context = Context } var newClass = requiresOperationContext ? Expression.MemberInit(Expression.New(targetType), bindContext) : Expression.MemberInit(Expression.New(targetType)); Expression callOperation; if (parameterInfos.Length == 0) { callOperation = Expression.Call(newClass, targetMethodInfo); } else if (parameterInfos.Length == 1) { MethodInfo deserializeMethod = callDeserializer.MakeGenericMethod(new Type[] { this.ParameterType }); // ParameterType obj = LZ4MessagePackSerializer.Deserialize<ParameterStructType>(HttpContext.Request.Body, FormatterResolver); var deserializedObj = Expression.Call(null, deserializeMethod, httpRequestBody, resolverProperty); callOperation = Expression.Call(newClass, targetMethodInfo, deserializedObj); } else { MethodInfo deserializeMethod = callDeserializer.MakeGenericMethod(new Type[] { this.ParameterType }); // ParameterStructType obj = LZ4MessagePackSerializer.Deserialize<ParameterStructType>(HttpContext.Request.Body, FormatterResolver); var deserialize = Expression.Call(null, deserializeMethod, httpRequestBody, resolverProperty); var obj = Expression.Parameter(ParameterType, "obj"); var assign = Expression.Assign(obj, deserialize); // obj.field1, obj.field2, ... var args = targetMethodInfo.GetParameters().Select(x => Expression.Field(obj, x.Name)).ToArray(); // new Class().Method(obj.field1, obj.field2, ...) var callMethod = Expression.Call(newClass, targetMethodInfo, args); // ParameterStructType obj = LZ4MessagePackSerializer.Deserialize<ParameterStructType>(HttpContext.Request.Body, FormatterResolver); // new Class().Method(obj.field1, obj.field2, ...) callOperation = Expression.Block(new[] { obj }, assign, callMethod); } // ParameterStructType obj = LZ4MessagePackSerializer.Deserialize<ParameterStructType>(HttpContext.Request.Body, FormatterResolver); // AsyncExecute(new Class().Method(obj.field1, obj.field2, ...)) var asyncExecuteMethodInfo = asyncRetunType != null ? typeof(OperationController).GetMethod(nameof(OperationController.AsyncFunction)).MakeGenericMethod(asyncRetunType) : typeof(OperationController).GetMethod(nameof(OperationController.AsyncAction)); var taskExecute = Expression.Call(null, asyncExecuteMethodInfo, operationContext, callOperation); var lambda = Expression.Lambda <Func <OperationContext, Task> >(taskExecute, operationContext); this.OperationAsync = lambda.Compile(); this.filters = option.GlobalFilters .Concat(targetType.GetTypeInfo().GetCustomAttributes <NetStitchFilterAttribute>(true)) .Concat(targetMethodInfo.GetCustomAttributes <NetStitchFilterAttribute>(true)) .OrderBy(x => x.Order) .ToArray(); this.OperationAsync = SetFilter(this.OperationAsync); }
public OperationContext(HttpContext httpContext, OperationController operationController, NetStitchOption option) { this.httpcontext = httpContext; this.operationController = operationController; this.option = option; }