コード例 #1
0
        public void Generate(GeneratorTypeContext context)
        {
            var classType = context.ClassType;

            if (context.InterfaceType == null)
            {
                var typeBuilder = context.ModuleBuilder.DefineType(
                    $"{classType.Name}_AspectFlare",
                    classType.Attributes
                    );

                typeBuilder.SetParent(classType);
                context.TypeBuilder = typeBuilder;
            }
            else
            {
                context.TypeBuilder = context.ModuleBuilder.DefineType(
                    $"<AspectFlare>{classType.Name}",
                    classType.Attributes,
                    typeof(object),
                    new Type[] { context.InterfaceType }
                    );
            }

            if (classType.IsGenericTypeDefinition)
            {
                GenerateGeneric(classType, context.TypeBuilder);
            }
        }
コード例 #2
0
        public void GenerateInit(GeneratorTypeContext context)
        {
            var initBuilder = context.TypeBuilder.DefineMethod(
                "<Proxy>__init",
                MethodAttributes.Private |
                MethodAttributes.HideBySig,
                CallingConventions.HasThis
                );

            var initGenerator = initBuilder.GetILGenerator();
            var typeLocal     = initGenerator.DeclareLocal(typeof(Type));
            var hasInterface  = context.InterfaceType != null;

            initGenerator.Emit(OpCodes.Ldarg_0);
            if (hasInterface)
            {
                initGenerator.Emit(OpCodes.Ldtoken, context.InterfaceType);
                initGenerator.Emit(OpCodes.Call, ReflectionInfoProvider.GetTypeFromHandle);
            }
            initGenerator.Emit(OpCodes.Ldtoken, context.ClassType);
            initGenerator.Emit(OpCodes.Call, ReflectionInfoProvider.GetTypeFromHandle);
            initGenerator.Emit(OpCodes.Ldtoken, context.TypeBuilder);
            initGenerator.Emit(OpCodes.Call, ReflectionInfoProvider.GetTypeFromHandle);
            initGenerator.Emit(OpCodes.Newobj, hasInterface ?
                               ReflectionInfoProvider.InterceptorWrapperCollectionByInterface :
                               ReflectionInfoProvider.InterceptorWrapperCollectionByClass
                               );
            initGenerator.Emit(OpCodes.Stfld, context.Wrappers);
            initGenerator.Emit(OpCodes.Ret);

            context.InitMethod = initBuilder;
        }
コード例 #3
0
ファイル: GeneratorContext.cs プロジェクト: JolyneStone/Rye
 public GeneratorContext(GeneratorTypeContext context)
 {
     this.TypeBuilder   = context.TypeBuilder;
     this.Wrappers      = context.Wrappers;
     this.ClassType     = context.ClassType;
     this.InterfaceType = context.InterfaceType;
     this.Interface     = context.Interface;
     this.InitMethod    = context.InitMethod;
     this.Token         = context.Token++;
 }
コード例 #4
0
 public override void Generate(GeneratorTypeContext context)
 {
     if (context.InterfaceType != null)
     {
         GenerateInterface(context);
     }
     else
     {
         GenerateClass(context);
     }
 }
コード例 #5
0
        private void GenerateClass(GeneratorTypeContext context)
        {
            var  classType         = context.ClassType;
            var  typeBuilder       = context.TypeBuilder;
            bool hasClassIntercept = classType.HasInterceptAttribute();

            foreach (var proxyMethod in classType.GetMethods(
                         BindingFlags.Instance |
                         BindingFlags.Public |
                         BindingFlags.NonPublic
                         ).Where(
                         x =>
                         x.IsVirtual &&
                         (x.IsPublic || x.IsFamily)
                         ))
            {
                if (proxyMethod.IsDefined(typeof(NonInterceptAttribute)))
                {
                    continue;
                }

                if (!proxyMethod.HasDefineInterceptAttribute() && !hasClassIntercept)
                {
                    continue;
                }

                if (proxyMethod.ReturnType.IsByRef)
                {
                    continue;
                }

                context.MethodHandles.Add(proxyMethod.MethodHandle);

                var baseParameterInfos = proxyMethod.GetParameters();

                // 定义方法
                MethodBuilder methodBuilder = typeBuilder.DefineMethod(
                    proxyMethod.Name,
                    proxyMethod.Attributes ^ MethodAttributes.NewSlot,
                    CallingConventions.HasThis | CallingConventions.Standard,
                    proxyMethod.ReturnType,
                    baseParameterInfos.Select(x => x.ParameterType).ToArray()
                    );

                methodBuilder.SetReturnType(proxyMethod.ReturnType);
                methodBuilder.SetMethodParameters(proxyMethod, baseParameterInfos);

                ILGenerator methodGenerator = methodBuilder.GetILGenerator();
                GenerateMethod(methodBuilder, proxyMethod, null, methodGenerator, context, baseParameterInfos);
                typeBuilder.DefineMethodOverride(methodBuilder, proxyMethod);
            }
        }
コード例 #6
0
        public void Generate(GeneratorTypeContext context)
        {
            context.Wrappers = context.TypeBuilder.DefineField(
                "<_wrappers>",
                typeof(InterceptorWrapperCollection),
                FieldAttributes.Private
                );

            if (context.InterfaceType != null)
            {
                context.Interface = context.TypeBuilder.DefineField(
                    $"<{context.ClassType.Name}>_i",
                    context.InterfaceType,
                    FieldAttributes.Private
                    );
            }
        }
コード例 #7
0
        protected void GenerateMethod(
            MethodBase methodBuilder,
            MethodBase classMethod,
            MethodInfo interfaceMethod,
            ILGenerator generator,
            GeneratorTypeContext typeContext,
            ParameterInfo[] parameters
            )
        {
            var context = GetMethodContext(
                methodBuilder,
                classMethod,
                interfaceMethod,
                generator,
                typeContext,
                parameters
                );

            GenerateDynamicMethod(context);
        }
コード例 #8
0
        private Type GenerateProxyType(Type interfaceType, Type classType)
        {
            var context = new GeneratorTypeContext
            {
                ModuleBuilder = _moduleBuilder,
                ClassType     = classType,
                InterfaceType = interfaceType
            };

            DefineTypeOperator.Generate(context);
            DefineFieldsOperator.Generate(context);

            ImplementConstructorsOperator.Generate(context);
            ImplementMethodsOperator.Generate(context);

            var proxyType = context.TypeBuilder.CreateTypeInfo();

            HandleCollection.AddHandles(proxyType.MetadataToken, context.MethodHandles);
            return(proxyType);
        }
コード例 #9
0
        private static GeneratorContext GetMethodContext(
            MethodBase builder,
            MethodBase proxyMethod,
            MethodInfo interfaceMethod,
            ILGenerator generator,
            GeneratorTypeContext typeContext,
            ParameterInfo[] parameters
            )
        {
            var context = new GeneratorContext(typeContext)
            {
                Generator       = generator,
                InterfaceMethod = interfaceMethod,
                Parameters      = proxyMethod.GetParameters().Select(x => new ParamInfo(x)).ToArray()
            };

            Type fieldType;

            if (proxyMethod is MethodInfo meth)
            {
                context.Method = meth;
                var returnType = meth.ReturnType;
                if (returnType.IsByRef)
                {
                    context.ReturnType = returnType;
                }
                else
                {
                    if (returnType == typeof(void))
                    {
                        context.ReturnType = returnType;
                        context.CallerType = CallerType.Void;
                        fieldType          = typeof(VoidCaller);
                    }
                    else if (!meth.IsDefined(typeof(StateMachineAttribute)))
                    {
                        context.ReturnType = returnType;
                        context.CallerType = CallerType.Return;
                        fieldType          = typeof(ReturnCaller <>).MakeGenericType(returnType);
                    }
                    else if (returnType == typeof(Task))
                    {
                        context.ReturnType = null;
                        context.CallerType = CallerType.Task;
                        fieldType          = typeof(TaskCaller);
                    }
                    else if (returnType.IsGenericType)
                    {
                        var type = returnType.GetGenericTypeDefinition();
                        context.ReturnType = returnType.GetGenericArguments()[0];
                        if (type == typeof(Task <>))
                        {
                            context.CallerType = CallerType.TaskOfT;
                            fieldType          = typeof(TaskCaller <>).MakeGenericType(context.ReturnType);
                        }
                        else if (type == typeof(ValueTask <>))
                        {
                            context.CallerType = CallerType.ValueTaskOfT;
                            fieldType          = typeof(ValueTaskCaller <>).MakeGenericType(context.ReturnType);
                        }
                        else
                        {
                            throw new InvalidOperationException("function return value error!");
                        }
                    }
                    else
                    {
                        throw new InvalidOperationException("function return value error!");
                    }

                    context.Caller        = context.TypeBuilder.DefineField($"<>_caller{context.Token}", fieldType, FieldAttributes.Private);
                    context.MethodBuilder = (MethodBuilder)builder;
                }
            }
            else if (proxyMethod is ConstructorInfo ctor)
            {
                context.Constructor        = ctor;
                context.ReturnType         = null;
                context.CallerType         = CallerType.Ctor;
                context.Caller             = context.TypeBuilder.DefineField($"<>_caller{context.Token}", typeof(VoidCaller), FieldAttributes.Private);
                context.ConstructorBuilder = (ConstructorBuilder)builder;
            }

            return(context);
        }
コード例 #10
0
 public abstract void Generate(GeneratorTypeContext context);
コード例 #11
0
        private void GeneratorConstructor(
            ConstructorBuilder methodBuilder,
            ConstructorInfo constructor,
            ILGenerator ctorGenerator,
            GeneratorTypeContext context,
            ParameterInfo[] parameters,
            bool isIntercept)
        {
            // 初始化
            // Ldarg_0 一般是方法开始的第一个指令
            ctorGenerator.Emit(OpCodes.Ldarg_0);
            ctorGenerator.Emit(OpCodes.Call, context.InitMethod);

            if (context.InterfaceType != null)
            {
                ctorGenerator.Emit(OpCodes.Ldarg_0);
                ctorGenerator.Emit(OpCodes.Call, ReflectionInfoProvider.ObjectConstructor);

                ctorGenerator.Emit(OpCodes.Ldarg_0);

                if (constructor == null && context.ClassType.IsValueType)
                {
                    ctorGenerator.DeclareLocal(context.ClassType);
                    ctorGenerator.Emit(OpCodes.Ldloca_S, 0);
                    ctorGenerator.Emit(OpCodes.Initobj, context.ClassType);
                    ctorGenerator.Emit(OpCodes.Ldloc_0);
                }
                else
                {
                    for (var i = 1; i <= parameters.Length; i++)
                    {
                        ctorGenerator.Emit(OpCodes.Ldarg_S, i);
                    }

                    ctorGenerator.Emit(OpCodes.Newobj, constructor);
                }

                if (context.ClassType.IsValueType)
                {
                    ctorGenerator.Emit(OpCodes.Box, context.ClassType);
                }

                ctorGenerator.Emit(OpCodes.Stfld, context.Interface);
            }
            else
            {
                if (isIntercept)
                {
                    context.MethodHandles.Add(constructor.MethodHandle);

                    // 调用基类构造函数 base(x)
                    // 注:这里的调用位置在C#代码中无法表示,因为在C#中调用基类构造函数必须在方法参数列表之后
                    GenerateMethod(methodBuilder, constructor, null, ctorGenerator, context, parameters);
                }
                else
                {
                    ctorGenerator.Emit(OpCodes.Ldarg_0);
                    for (var i = 1; i <= parameters.Length; i++)
                    {
                        ctorGenerator.Emit(OpCodes.Ldarg_S, i);
                    }

                    ctorGenerator.Emit(OpCodes.Call, constructor);
                }
            }

            ctorGenerator.Emit(OpCodes.Ret);
        }
コード例 #12
0
        public override void Generate(GeneratorTypeContext context)
        {
            GenerateInit(context);
            var  classType         = context.ClassType;
            var  typeBuilder       = context.TypeBuilder;
            bool hasClassIntercept = classType.HasInterceptAttribute();

            foreach (var ctor in classType.GetConstructors(
                         BindingFlags.CreateInstance |
                         BindingFlags.Instance |
                         BindingFlags.Public |
                         BindingFlags.NonPublic
                         ).Where(
                         x =>
                         x.IsPublic ||
                         x.IsFamily ||
                         !(x.IsAssembly || x.IsFamilyAndAssembly || x.IsFamilyOrAssembly)
                         ))
            {
                var baseParameterInfos = ctor.GetParameters();
                var parameters         = baseParameterInfos
                                         .Select(x => x.ParameterType)
                                         .ToArray();

                // 定义构造函数
                ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.HasThis,
                    parameters
                    );

                bool isIntercept = true;
                if (ctor.IsDefined(typeof(NonInterceptAttribute)))
                {
                    isIntercept = false;
                }
                if (!ctor.HasDefineInterceptAttribute() && !hasClassIntercept)
                {
                    isIntercept = false;
                }

                constructorBuilder.SetMethodParameters(baseParameterInfos);
                ILGenerator ctorGenerator = constructorBuilder.GetILGenerator();
                GeneratorConstructor(
                    constructorBuilder,
                    ctor,
                    ctorGenerator,
                    context,
                    baseParameterInfos,
                    isIntercept
                    );
            }

            if (context.InterfaceType != null &&
                context.ClassType.IsValueType)
            {
                ConstructorBuilder constructorBuilder = typeBuilder.DefineConstructor(
                    MethodAttributes.Public,
                    CallingConventions.HasThis,
                    null
                    );

                ILGenerator ctorGenerator = constructorBuilder.GetILGenerator();
                GeneratorConstructor(
                    constructorBuilder,
                    null,
                    ctorGenerator,
                    context,
                    null,
                    false
                    );
            }
        }
コード例 #13
0
        private void GenerateInterface(GeneratorTypeContext context)
        {
            var interfaceType = context.InterfaceType;
            var impNames      = interfaceType.GetMethods(
                BindingFlags.Public |
                BindingFlags.Instance |
                BindingFlags.DeclaredOnly
                );

            var impImpNames = impNames.Select(x => x.Name);                                // 隐式接口实现方法名称
            var expImpNames = impNames.Select(x => interfaceType.FullName + "." + x.Name); // 显示接口实现方法名称


            var  classType             = context.ClassType;
            var  typeBuilder           = context.TypeBuilder;
            bool hasClassIntercept     = classType.HasInterceptAttribute();
            bool hasInterfaceIntercept = interfaceType.HasInterceptAttribute();
            var  interfaceMethods      = interfaceType.GetMethods(
                BindingFlags.Public |
                BindingFlags.Instance
                //BindingFlags.DeclaredOnly
                );

            foreach (var proxyMethod in classType.GetMethods(
                         BindingFlags.Instance |
                         BindingFlags.Public |
                         BindingFlags.NonPublic
                         ).Where(
                         x => x.IsVirtual
                         ))
            {
                //if (proxyMethod.IsDefined(typeof(NonInterceptAttribute)))
                //{
                //    continue;
                //}

                if (!impImpNames.Contains(proxyMethod.Name) && !expImpNames.Contains(proxyMethod.Name))
                {
                    continue;
                }

                //if (!proxyMethod.HasDefineInterceptAttribute() && !hasClassIntercept && !hasInterfaceIntercept)
                //{
                //    continue;
                //}


                context.MethodHandles.Add(proxyMethod.MethodHandle);

                var baseParameterInfos = proxyMethod.GetParameters();

                // 定义方法
                MethodBuilder methodBuilder = typeBuilder.DefineMethod(
                    interfaceType.FullName + "." + proxyMethod.Name,
                    MethodAttributes.Private | MethodAttributes.HideBySig |
                    MethodAttributes.NewSlot | MethodAttributes.Virtual |
                    MethodAttributes.Final,
                    CallingConventions.HasThis | CallingConventions.Standard,
                    proxyMethod.ReturnType,
                    baseParameterInfos.Select(x => x.ParameterType).ToArray()
                    );

                methodBuilder.SetReturnType(proxyMethod.ReturnType);
                methodBuilder.SetMethodParameters(proxyMethod, baseParameterInfos);

                ILGenerator methodGenerator = methodBuilder.GetILGenerator();

                var dotIndex        = proxyMethod.Name.LastIndexOf('.');
                var interfaceMethod = impNames.First(x =>
                                                     x.Name == proxyMethod.Name.Substring(dotIndex == -1 ? 0 : dotIndex));

                GenerateMethod(methodBuilder, proxyMethod, interfaceMethod, methodGenerator, context, baseParameterInfos);
                typeBuilder.DefineMethodOverride(methodBuilder, interfaceMethod);
            }
        }