Beispiel #1
0
        private static MethodDefinition CreateBaseCallMethod(ModuleDefinition md, MethodReference baseMethod)
        {
            var methodKey              = Core.Helper.GetMethodKey(baseMethod.Name, baseMethod.Parameters.Select(x => x.ParameterType.FullName).ToArray());
            var methodName             = "HotReloadingBase_" + baseMethod.Name;
            var hotReloadingBaseMethod = new MethodDefinition(methodName, MethodAttributes.Private | MethodAttributes.HideBySig, md.ImportReference(typeof(void)));

            foreach (var parameter in baseMethod.GenericParameters)
            {
                hotReloadingBaseMethod.GenericParameters.Add(parameter);
            }

            hotReloadingBaseMethod.ReturnType = baseMethod.ReturnType;
            foreach (var parameter in baseMethod.Parameters)
            {
                TypeReference parameterType = parameter.ParameterType;
                hotReloadingBaseMethod.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameterType)
                {
                    IsIn       = parameter.IsIn,
                    IsOut      = parameter.IsOut,
                    IsOptional = parameter.IsOptional
                });
            }

            var retVar           = new VariableDefinition(md.ImportReference(typeof(object)));
            var baseCallComposer = new InstructionComposer(md)
                                   .LoadArg_0();

            foreach (var parameter in hotReloadingBaseMethod.Parameters)
            {
                baseCallComposer.LoadArg(parameter);
            }

            baseCallComposer.BaseCall(baseMethod);

            if (hotReloadingBaseMethod.ReturnType.FullName != "System.Void")
            {
                var returnVariable = new VariableDefinition(hotReloadingBaseMethod.ReturnType);

                hotReloadingBaseMethod.Body.Variables.Add(returnVariable);

                baseCallComposer.Store(returnVariable);
                baseCallComposer.Load(returnVariable);
            }

            baseCallComposer.Return();

            foreach (var instruction in baseCallComposer.Instructions)
            {
                hotReloadingBaseMethod.Body.GetILProcessor().Append(instruction);
            }

            return(hotReloadingBaseMethod);
        }
Beispiel #2
0
        private void AddOverrideMethod(TypeDefinition type,
                                       ModuleDefinition md,
                                       MethodReference getInstanceMethod,
                                       List <MethodDefinition> existingMethods)
        {
            if (type.BaseType == null)
            {
                return;
            }

            var overridableMethods = GetOverridableMethods(type, md);

            var baseMethodCalls = new List <MethodReference>();

            foreach (var overridableMethod in overridableMethods)
            {
                if (existingMethods.Any(x => x.FullName == overridableMethod.Method.FullName))
                {
                    continue;
                }
                var baseMethod = overridableMethod.BaseMethodReference;
                //Ignore method with ref parameter
                if (baseMethod.Parameters.Any(x => x.ParameterType is ByReferenceType))
                {
                    continue;
                }
                baseMethodCalls.Add(baseMethod);

                if (!type.Methods.Any(x => x.IsEqual(overridableMethod.Method)))
                {
                    var method = overridableMethod.Method;

                    var returnType = method.ReturnType;

                    var composer = new InstructionComposer(md);

                    composer.LoadArg_0();

                    foreach (var parameter in method.Parameters)
                    {
                        composer.LoadArg(parameter);
                    }

                    composer.BaseCall(baseMethod);

                    if (overridableMethod.Method.ReturnType.FullName != "System.Void")
                    {
                        var returnVariable = new VariableDefinition(returnType);

                        method.Body.Variables.Add(returnVariable);

                        composer.Store(returnVariable);
                        composer.Load(returnVariable);
                    }

                    composer.Return();

                    foreach (var instruction in composer.Instructions)
                    {
                        method.Body.GetILProcessor().Append(instruction);
                    }

                    WrapMethod(md, type, method, getInstanceMethod);

                    method.DeclaringType = type;
                    type.Methods.Add(method);
                }
            }

            foreach (var baseMethod in baseMethodCalls)
            {
                //Ignore optional
                if (baseMethod.Parameters.Any(x => x.IsOptional))
                {
                    continue;
                }
                var hotReloadingBaseMethod = CreateBaseCallMethod(md, baseMethod);

                type.Methods.Add(hotReloadingBaseMethod);
            }
        }
        private void AddOverrideMethod(TypeDefinition type, ModuleDefinition md, MethodReference getInstanceMethod)
        {
            if (type.BaseType == null)
            {
                return;
            }

            var overridableMethods = GetOverridableMethods(type, md);

            var baseMethodCalls = new List <MethodReference>();

            foreach (var overridableMethod in overridableMethods)
            {
                MethodReference baseMethod = GetBaseMethod(overridableMethod);
                //Ignore method with ref parameter
                if (baseMethod.Parameters.Any(x => x.ParameterType is ByReferenceType))
                {
                    continue;
                }
                baseMethodCalls.Add(baseMethod);

                if (!type.Methods.Any(x => x.IsEqual(overridableMethod.Method)))
                {
                    var method = overridableMethod.Method;

                    var returnType = method.ReturnType;

                    var composer = new InstructionComposer(md);

                    composer.LoadArg_0();

                    foreach (var parameter in method.Parameters)
                    {
                        composer.LoadArg(parameter);
                    }

                    composer.BaseCall(baseMethod);

                    if (overridableMethod.Method.ReturnType.FullName != "System.Void")
                    {
                        var returnVariable = new VariableDefinition(returnType);

                        method.Body.Variables.Add(returnVariable);

                        composer.Store(returnVariable);
                        composer.Load(returnVariable);
                    }

                    composer.Return();

                    foreach (var instruction in composer.Instructions)
                    {
                        method.Body.GetILProcessor().Append(instruction);
                    }

                    WrapMethod(md, type, method, getInstanceMethod);

                    method.DeclaringType = type;
                    type.Methods.Add(method);
                }
            }

            foreach (var baseMethod in baseMethodCalls)
            {
                //Ignore optional
                if (baseMethod.Parameters.Any(x => x.IsOptional))
                {
                    continue;
                }
                var methodKey              = Core.Helper.GetMethodKey(baseMethod.Name, baseMethod.Parameters.Select(x => x.ParameterType.FullName).ToArray());
                var methodName             = "HotReloadingBase_" + baseMethod.Name;
                var hotReloadingBaseMethod = new MethodDefinition(methodName, MethodAttributes.Private | MethodAttributes.HideBySig, md.ImportReference(typeof(void)));

                foreach (var parameter in baseMethod.GenericParameters)
                {
                    hotReloadingBaseMethod.GenericParameters.Add(parameter);
                }

                hotReloadingBaseMethod.ReturnType = baseMethod.ReturnType;
                foreach (var parameter in baseMethod.Parameters)
                {
                    TypeReference parameterType = parameter.ParameterType;
                    hotReloadingBaseMethod.Parameters.Add(new ParameterDefinition(parameter.Name, parameter.Attributes, parameterType)
                    {
                        IsIn       = parameter.IsIn,
                        IsOut      = parameter.IsOut,
                        IsOptional = parameter.IsOptional
                    });
                }

                var retVar           = new VariableDefinition(md.ImportReference(typeof(object)));
                var baseCallComposer = new InstructionComposer(md)
                                       .LoadArg_0();

                foreach (var parameter in hotReloadingBaseMethod.Parameters)
                {
                    baseCallComposer.LoadArg(parameter);
                }

                baseCallComposer.BaseCall(baseMethod);

                if (hotReloadingBaseMethod.ReturnType.FullName != "System.Void")
                {
                    var returnVariable = new VariableDefinition(hotReloadingBaseMethod.ReturnType);

                    hotReloadingBaseMethod.Body.Variables.Add(returnVariable);

                    baseCallComposer.Store(returnVariable);
                    baseCallComposer.Load(returnVariable);
                }

                baseCallComposer.Return();

                foreach (var instruction in baseCallComposer.Instructions)
                {
                    hotReloadingBaseMethod.Body.GetILProcessor().Append(instruction);
                }

                type.Methods.Add(hotReloadingBaseMethod);
            }
        }