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); }
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); } }