void UpdateMagicPrefill(TypeDefinition magicType) { var fieldTypesMap = magicType.Fields.FirstOrDefault(f => f.Name == "typesMap"); if (fieldTypesMap == null) { return; } var methodPrefill = Extensions.GetMethod(magicType, "Prefill"); if (methodPrefill == null) { return; } var typeDictionary = _context.GetType("mscorlib", "System.Collections.Generic.Dictionary`2"); var ctorDictionary = Extensions.GetMethod(typeDictionary, ".ctor", new string[] { "System.Int32" }); var methodSetItem = Extensions.GetMethod(typeDictionary, "set_Item", new string[] { "TKey", "TValue" }); var genericTypeDictionary = new GenericInstanceType(typeDictionary); genericTypeDictionary.GenericArguments.Add(_context.GetType("mscorlib", "System.String")); genericTypeDictionary.GenericArguments.Add(_context.GetType("mscorlib", "System.Int32")); var genericMethodDictionaryCtor = CreateGenericMethodReference(ctorDictionary, genericTypeDictionary); var genericMethodDictionarySetItem = CreateGenericMethodReference(methodSetItem, genericTypeDictionary); var importedMethodSetItem = magicType.Module.ImportReference(genericMethodDictionarySetItem); var instructions = methodPrefill.Body.Instructions; instructions.Clear(); instructions.Add(Extensions.CreateLoadArraySizeOrOffsetInstruction(marshalTypes.Count)); instructions.Add(Instruction.Create(OpCodes.Newobj, magicType.Module.ImportReference(genericMethodDictionaryCtor))); instructions.Add(Instruction.Create(OpCodes.Stsfld, fieldTypesMap)); int idx = 0; foreach (var type in marshalTypes) { instructions.Add(Instruction.Create(OpCodes.Ldsfld, fieldTypesMap)); instructions.Add(Instruction.Create(OpCodes.Ldstr, type.FullName.Replace("/__<$>_jni_marshal_methods", "").Replace("/", "+"))); instructions.Add(Extensions.CreateLoadArraySizeOrOffsetInstruction(idx++)); instructions.Add(Instruction.Create(OpCodes.Callvirt, importedMethodSetItem)); } instructions.Add(Instruction.Create(OpCodes.Ret)); }
MethodDefinition GetKeepAliveMethod() { var corlibAssembly = GetCorlibAssembly(); if (corlibAssembly == null) { return(null); } var gcType = Extensions.GetType(corlibAssembly, "System.GC"); if (gcType == null) { return(null); } return(Extensions.GetMethod(gcType, "KeepAlive", new string [] { "System.Object" })); }
void UpdateMagicRegistration() { TypeDefinition magicType = _context.GetType("Mono.Android", "Android.Runtime.AndroidTypeManager/MagicRegistrationMap"); if (magicType == null) { return; } MethodDefinition magicCall = Extensions.GetMethod(magicType, "CallRegisterMethodByIndex"); if (magicCall == null) { return; } var switchMethods = new MethodReference [marshalTypes.Count]; var module = magicType.Module; int idx = 0; foreach (var type in marshalTypes) { var md = Extensions.GetMethod(type, "__RegisterNativeMembers"); if (md == null) { return; } var resolved = md.Resolve(); if (resolved == null) { return; } switchMethods [idx++] = module.ImportReference(resolved); } UpdateMagicPrefill(magicType); UpdateRegistrationSwitch(magicCall, switchMethods); }
void UpdateRegistrationSwitch(MethodDefinition method, MethodReference[] switchMethods) { var instructions = method.Body.Instructions; var module = method.DeclaringType.Module; var switchInstructions = new Instruction [switchMethods.Length]; instructions.Clear(); var typeNullable = _context.GetType("mscorlib", "System.Nullable`1"); var methodGetValueOrDefault = Extensions.GetMethod(typeNullable, "GetValueOrDefault"); var genericTypeNullable = new GenericInstanceType(typeNullable); genericTypeNullable.GenericArguments.Add(_context.GetType("mscorlib", "System.Int32")); var typeIdxVariable = new VariableDefinition(module.ImportReference(genericTypeNullable)); method.Body.Variables.Clear(); method.Body.Variables.Add(typeIdxVariable); instructions.Add(Instruction.Create(OpCodes.Ldarg_1)); instructions.Add(Instruction.Create(OpCodes.Stloc_0)); instructions.Add(Instruction.Create(OpCodes.Ldloca_S, typeIdxVariable)); var genericMethodGetValueOrDefault = CreateGenericMethodReference(methodGetValueOrDefault, genericTypeNullable); instructions.Add(Instruction.Create(OpCodes.Call, module.ImportReference(genericMethodGetValueOrDefault))); for (var i = 0; i < switchMethods.Length; i++) { switchInstructions [i] = Instruction.Create(OpCodes.Ldtoken, switchMethods [i].DeclaringType); } var typeType = _context.GetType("mscorlib", "System.Type"); var methodGetTypeFromHandle = _context.GetMethod("mscorlib", "System.Type", "GetTypeFromHandle", new string[] { "System.RuntimeTypeHandle" }); var callDelegateStart = Instruction.Create(OpCodes.Call, module.ImportReference(methodGetTypeFromHandle)); instructions.Add(Instruction.Create(OpCodes.Switch, switchInstructions)); for (var i = 0; i < switchMethods.Length; i++) { instructions.Add(switchInstructions [i]); instructions.Add(Instruction.Create(OpCodes.Br, callDelegateStart)); } instructions.Add(Instruction.Create(OpCodes.Ldc_I4_0)); instructions.Add(Instruction.Create(OpCodes.Ret)); var actionType = _context.GetType("mscorlib", "System.Action`1"); var genericActionType = new GenericInstanceType(actionType); var argsType = _context.GetType("Java.Interop", "Java.Interop.JniNativeMethodRegistrationArguments"); genericActionType.GenericArguments.Add(argsType); MarkType(genericActionType); var actionInvoke = Extensions.GetMethod(actionType, "Invoke", new string[] { "T" }); var methodGetMethod = _context.GetMethod("mscorlib", "System.Type", "GetMethod", new string[] { "System.String" }); var typeMethodInfo = _context.GetType("mscorlib", "System.Reflection.MethodInfo"); var methodCreateDelegate = _context.GetMethod("mscorlib", "System.Reflection.MethodInfo", "CreateDelegate", new string[] { "System.Type" }); instructions.Add(callDelegateStart); instructions.Add(Instruction.Create(OpCodes.Ldstr, "__RegisterNativeMembers")); instructions.Add(Instruction.Create(OpCodes.Call, module.ImportReference(methodGetMethod))); instructions.Add(Instruction.Create(OpCodes.Ldtoken, module.ImportReference(genericActionType))); instructions.Add(Instruction.Create(OpCodes.Call, module.ImportReference(methodGetTypeFromHandle))); instructions.Add(Instruction.Create(OpCodes.Callvirt, module.ImportReference(methodCreateDelegate))); instructions.Add(Instruction.Create(OpCodes.Castclass, module.ImportReference(genericActionType))); var genericActionInvoke = CreateGenericMethodReference(actionInvoke, genericActionType); instructions.Add(Instruction.Create(OpCodes.Ldarg_0)); instructions.Add(Instruction.Create(OpCodes.Callvirt, module.ImportReference(genericActionInvoke))); instructions.Add(Instruction.Create(OpCodes.Ldc_I4_1)); instructions.Add(Instruction.Create(OpCodes.Ret)); }