Exemple #1
0
        public static Type GenerateService(Type typeForMethods, Type typeRealization)
        {
            var interfaceType = InterfaceGenerator.GenerateInterface(typeForMethods);

            AssemblyName assemblyName = new AssemblyName("MagicOnionServer.DynamicServices");
            string       moduleName   = String.Format("{0}.dll", assemblyName.Name);

            var assembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
            var module   = assembly.DefineDynamicModule(moduleName);

            var type = module.DefineType("DynamicMyFirstService",
                                         TypeAttributes.Public,
                                         typeof(ServiceBase <>).MakeGenericType(interfaceType),
                                         new[] { interfaceType });

            var fld  = type.DefineField("_service", typeRealization, FieldAttributes.Private | FieldAttributes.InitOnly);
            var ctor = type.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, Type.EmptyTypes);
            var il   = ctor.GetILGenerator();

            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Call, type.BaseType.GetConstructor(BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, null));
            il.Emit(OpCodes.Ldarg_0);
            il.Emit(OpCodes.Newobj, typeRealization.GetConstructor(Type.EmptyTypes));
            il.Emit(OpCodes.Stfld, fld);
            il.Emit(OpCodes.Ret);

            foreach (var m in interfaceType.GetMethods())
            {
                if (!m.IsAbstract)
                {
                    continue;
                }

                var realMet = typeRealization.GetMethod(m.Name);
                // TODO Добавить проверку на наличие метода и перегрузки

                var met = type.DefineMethod(m.Name,
                                            MethodAttributes.Public | MethodAttributes.ReuseSlot | MethodAttributes.Virtual, //| MethodAttributes.HideBySig,
                                            CallingConventions.HasThis,
                                            m.ReturnType,
                                            m.GetParameters().Select(p => p.ParameterType).ToArray()
                                            );
                il = met.GetILGenerator();
                il.Emit(OpCodes.Ldarg_0);
                il.Emit(OpCodes.Ldfld, fld);
                int paramCnt = m.GetParameters().Length;
                for (int j = 0; j < paramCnt; j++)
                {
                    il.Emit(OpCodes.Ldarg, j + 1);
                }
                il.Emit(OpCodes.Call, realMet);

                Type retType = realMet.ReturnType;
                if (!retType.IsGenericType || retType.GetGenericTypeDefinition() != typeof(UnaryResult <>))
                {
                    if (retType == typeof(void))
                    {
                        retType = typeof(MessagePack.Nil);
                        il.Emit(OpCodes.Ldsfld, retType.GetField(nameof(MessagePack.Nil.Default)));
                    }
                    retType = typeof(UnaryResult <>).MakeGenericType(retType);
                    il.Emit(OpCodes.Newobj, retType.GetConstructor(new[] { retType.GenericTypeArguments[0] }));
                }

                il.Emit(OpCodes.Ret);
            }

            return(type.CreateTypeInfo().AsType());
        }