示例#1
0
        private void ComposeInstanceMethodInstructions(TypeDefinition type, MethodDefinition method, VariableDefinition delegateVariable, VariableDefinition boolVariable, VariableDefinition methodKeyVariable, Instruction firstInstruction, ParameterDefinition[] parameters, InstructionComposer composer, MethodReference getInstanceMethod, ModuleDefinition md)
        {
            if (method.IsConstructor)
            {
                var arrayListConstructor          = typeof(ArrayList).GetConstructor(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance, null, new Type[] { }, null);
                var arrayListConstructorReference = md.ImportReference(arrayListConstructor);
                composer
                .LoadArg_0()
                .NewObject(arrayListConstructorReference)
                .Store(ctorParameters);

                foreach (var parameter in method.Parameters)
                {
                    composer.LoadArg_0()
                    .Load(ctorParameters)
                    .LoadArg(parameter);
                    if (parameter.ParameterType.IsValueType)
                    {
                        composer.Box(md.ImportReference(parameter.ParameterType));
                    }
                    composer
                    .InstanceCall(new Method
                    {
                        ParentType         = typeof(ArrayList),
                        MethodName         = "Add",
                        ParameterSignature = new Type[] { typeof(Object) }
                    })
                    .Pop();
                }
            }
            composer
            .Load(method.Name)
            .LoadArray(parameters.Length, typeof(string), parameters.Select(x => x.ParameterType.FullName).ToArray())
            .StaticCall(new Method
            {
                ParentType         = typeof(Core.Helper),
                MethodName         = nameof(Core.Helper.GetMethodKey),
                ParameterSignature = new[] { typeof(string), typeof(string[]) }
            }).
            Store(methodKeyVariable)
            .LoadArg_0()
            .Load(methodKeyVariable)
            .InstanceCall(getInstanceMethod)
            .Store(delegateVariable)
            .Load(delegateVariable)
            .IsNotNull()
            .Store(boolVariable)
            .Load(boolVariable)
            .MoveToWhenFalse(firstInstruction)
            .NoOperation()
            .Load(delegateVariable)
            .LoadArray(parameters, true)
            .InstanceCall(new Method
            {
                ParentType         = typeof(Delegate),
                MethodName         = nameof(Delegate.DynamicInvoke),
                ParameterSignature = new[] { typeof(object[]) }
            });
        }
示例#2
0
        private static PropertyDefinition CreateInstanceMethodsProperty(ModuleDefinition md, TypeDefinition type, out MethodDefinition instanceMethodGetters)
        {
            var instaceMethodType = md.ImportReference(typeof(Dictionary <string, Delegate>));
            var field             = type.CreateField(md, "instanceMethods", instaceMethodType);
            var fieldReference    = field.GetReference();

            var returnComposer = new InstructionComposer(md)
                                 .Load_1()
                                 .Return();

            var getFieldComposer = new InstructionComposer(md)
                                   .LoadArg_0()
                                   .Load(fieldReference)
                                   .Store_1()
                                   .MoveTo(returnComposer.Instructions.First());

            var initializeField = new InstructionComposer(md)
                                  .NoOperation()
                                  .LoadArg_0()
                                  .LoadArg_0()
                                  .StaticCall(new Method
            {
                ParentType         = typeof(Runtime),
                MethodName         = nameof(Runtime.GetInitialInstanceMethods),
                ParameterSignature = new[] { typeof(IInstanceClass) }
            })
                                  .Store(fieldReference)
                                  .NoOperation();

            var getterComposer = new InstructionComposer(md);

            getterComposer.LoadArg_0()
            .Load(fieldReference)
            .LoadNull()
            .CompareEqual()
            .Store_0()
            .Load_0()
            .MoveToWhenFalse(getFieldComposer.Instructions.First())
            .Append(initializeField)
            .Append(getFieldComposer)
            .Append(returnComposer);

            instanceMethodGetters = type.CreateGetter(md, "InstanceMethods", instaceMethodType, getterComposer.Instructions, vir: true);

            var boolVariable = new VariableDefinition(md.ImportReference(typeof(bool)));

            instanceMethodGetters.Body.Variables.Add(boolVariable);

            var delegateVariable = new VariableDefinition(md.ImportReference(typeof(Delegate)));

            instanceMethodGetters.Body.Variables.Add(delegateVariable);

            return(type.CreateProperty("InstanceMethods", instaceMethodType, instanceMethodGetters, null));
        }
 private static void ComposeInstanceMethodInstructions(TypeDefinition type, MethodDefinition method, VariableDefinition delegateVariable, VariableDefinition boolVariable, Instruction firstInstruction, ParameterDefinition[] parameters, InstructionComposer composer, MethodDefinition getInstanceMethod)
 {
     composer.LoadArg_0()
     .LoadStr(method.Name)
     .InstanceCall(getInstanceMethod)
     .Store(delegateVariable)
     .Load(delegateVariable)
     .IsNotNull()
     .Store(boolVariable)
     .Load(boolVariable)
     .MoveToWhenFalse(firstInstruction)
     .NoOperation()
     .Load(delegateVariable)
     .LoadArray(parameters, true)
     .InstanceCall(new Method
     {
         ParentType         = typeof(Delegate),
         MethodName         = nameof(Delegate.DynamicInvoke),
         ParameterSignature = new[] { typeof(object[]) }
     });
 }
示例#4
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);
            }
        }