public static void GenerateWrapperMethodPost(MethodInfo methodInfo, Type modelType, LambdaExpression lambda, TypeBuilder typeBuilder, FieldInfo delegateField, IDictionary <ParameterExpression, FieldBuilder> innerFields, DryvControllerGenerationContext context, DryvDynamicControllerOptions options) { var method = lambda.Type.GetMethod("Invoke"); var methodBuilder = ControllerMethodGenerator.CreateMethodBuilder(typeBuilder, methodInfo.Name, lambda.ReturnType, new[] { modelType }, context, options); var parameterBuilder = methodBuilder.DefineParameter(1, ParameterAttributes.None, "model"); parameterBuilder.SetCustomAttribute(ControllerAttributeGenerator.CreateAttributeBuilder <FromBodyAttribute>()); ControllerAttributeGenerator.SetAttribute <HttpPostAttribute>(methodBuilder); ControllerMethodGenerator.AddRoutingAttribute(methodBuilder, context, options); var il = methodBuilder.GetILGenerator(); il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, delegateField); foreach (var parameter in lambda.Parameters) { if (innerFields.TryGetValue(parameter, out var field)) { il.Emit(OpCodes.Ldarg_0); il.Emit(OpCodes.Ldfld, field); } else if (parameter.Type == modelType) { il.Emit(OpCodes.Ldarg_1); } } il.Emit(OpCodes.Callvirt, method); il.Emit(OpCodes.Ret); }
public Assembly CreateControllerAssembly(MethodCallExpression methodExpression, Type modelType) { var methodInfo = methodExpression.Method; var key = GetCacheKey(methodInfo); return(Cache.GetOrAdd(key, _ => { var assemblyIndex = ++assemblyCount; var typeNameBase = $"DryvDynamic{assemblyIndex}"; var baseType = typeof(Controller); var currentAssembly = Assembly.GetExecutingAssembly(); var assemblyName = new AssemblyName($"DryvDynamicAssembly{assemblyIndex}") { CodeBase = currentAssembly.CodeBase, }; var assemblyBuilder = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndCollect); var moduleBuilder = assemblyBuilder.DefineDynamicModule(assemblyName.Name); var typeBuilder = moduleBuilder.DefineType($"{NameSpace}.{typeNameBase}Controller", TypeAttributes.Class | TypeAttributes.Public, baseType); var context = new DryvControllerGenerationContext(typeBuilder, methodInfo); ControllerAttributeGenerator.AddCustomAttributes(context, this.options.Value.MapControllerFilters, typeBuilder.SetCustomAttribute); var parameters = FindParameters(methodExpression); var modelParameter = parameters.Find(p => p.Type == modelType); var lambda = Expression.Lambda(methodExpression, parameters); var delegateField = typeBuilder.DefineField("_delegate", lambda.Type, FieldAttributes.Private | FieldAttributes.Static); parameters.Remove(modelParameter); var innerFields = parameters.ToDictionary( p => p, p => typeBuilder.DefineField(p.Name, p.Type, FieldAttributes.Private)); ControllerCtorGenerator.GenerateConstructor(typeBuilder, baseType, innerFields.Values.ToList()); if (this.options.Value.HttpMethod == DryvDynamicControllerMethods.Post) { ControllerMethodGenerator.GenerateWrapperMethodPost(methodInfo, modelType, lambda, typeBuilder, delegateField, innerFields, context, this.options.Value); } else { ControllerMethodGenerator.GenerateWrapperMethodGet(methodInfo, modelType, methodExpression, lambda, typeBuilder, delegateField, innerFields, context, this.options.Value); } var type = typeBuilder.CreateType(); var field = type.GetField("_delegate", BindingFlags.Static | BindingFlags.NonPublic); Debug.Assert(field != null); field.SetValue(null, lambda.Compile()); //var generator = new Lokad.ILPack.AssemblyGenerator(); //generator.GenerateAssembly(assemblyBuilder, $"EMIT.dll"); //Process.Start(new ProcessStartInfo //{ // UseShellExecute = true, // WindowStyle = ProcessWindowStyle.Normal, // FileName = "dotnet", // Arguments = $"ildasm EMIT.dll -o EMIT.ildasm --force", //}).WaitForExit(); return assemblyBuilder; })); }