Exemplo n.º 1
0
        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);
        }
Exemplo n.º 2
0
        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;
            }));
        }