示例#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);
        }
示例#2
0
        private static MethodBuilder CreateMethodBuilder(TypeBuilder typeBuilder, string methodName, Type returnType, Type[] parameterTypes, DryvControllerGenerationContext context, DryvDynamicControllerOptions options)
        {
            var methodBuilder = typeBuilder.DefineMethod(methodName, MethodAttributes.Public, returnType, parameterTypes);

            ControllerAttributeGenerator.AddCustomAttributes(context, options.MapActionFilters, methodBuilder.SetCustomAttribute);

            return(methodBuilder);
        }
示例#3
0
        public static void GenerateWrapperMethodGet(MethodInfo methodInfo, Type modelType, MethodCallExpression methodExpression, LambdaExpression lambda, TypeBuilder typeBuilder, FieldInfo delegateField, IDictionary <ParameterExpression, FieldBuilder> innerFields, DryvControllerGenerationContext context, DryvDynamicControllerOptions options)
        {
            var memberFinder = new ControllerGenerator.MemberFinder(modelType);

            memberFinder.Visit(methodExpression);
            var properties = memberFinder.FoundMemberExpressions.Select(e => e.Member).Distinct().OfType <PropertyInfo>().ToList();

            var method            = lambda.Type.GetMethod("Invoke");
            var methodBuilder     = CreateMethodBuilder(typeBuilder, methodInfo.Name, lambda.ReturnType, properties.Select(p => p.PropertyType).ToArray(), context, options);
            var index             = 1;
            var parameterBuilders = properties.ToDictionary(
                p => p,
                p => methodBuilder.DefineParameter(index++, ParameterAttributes.None, p.Name));

            ControllerAttributeGenerator.SetAttribute <HttpGetAttribute>(methodBuilder);
            AddRoutingAttribute(methodBuilder, context, options);

            var il            = methodBuilder.GetILGenerator();
            var modelVariable = il.DeclareLocal(modelType);

            var ctor = modelType.GetConstructors().First(c => !c.GetParameters().Any());

            il.Emit(OpCodes.Newobj, ctor);

            index = 1;

            foreach (var builder in parameterBuilders)
            {
                il.Emit(OpCodes.Dup);
                il.Emit(OpCodes.Ldarg, index++);
                il.Emit(OpCodes.Callvirt, builder.Key.SetMethod);
            }

            il.Emit(OpCodes.Stloc_S, modelVariable);

            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.Ldloc_S, modelVariable);
                }
            }

            il.Emit(OpCodes.Callvirt, method);

            il.Emit(OpCodes.Ret);
        }
示例#4
0
        private static void AddRoutingAttribute(MethodBuilder methodBuilder, DryvControllerGenerationContext context, DryvDynamicControllerOptions options)
        {
            if (options.MapRouteTemplate == null)
            {
                return;
            }

            var template = options.MapRouteTemplate(context);

            ControllerAttributeGenerator.SetAttribute <RouteAttribute>(methodBuilder, template);
        }
示例#5
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;
            }));
        }