public void ApplyPatches(IEnumerable <Patch> enabledPatches, ISymbolTranslator symbolTranslator) { InitOriginalType(); CollectReplacements(symbolTranslator); // We already have the list of types we should check for replacement methods, it's the contents of // typeReplacements. This dictionary will be modified during fixups, though, so to keep things // consistent, iterate on a copy instead of the field itself. Dictionary <string, TypeReference> typeReplacementsCopy = new Dictionary <string, TypeReference>(typeReplacements); foreach (KeyValuePair <string, TypeReference> nameAndTargetPair in typeReplacementsCopy) { TypeDefinition decoyType = source.GetType(nameAndTargetPair.Key); TypeDefinition targetType = nameAndTargetPair.Value as TypeDefinition; if (targetType != null) { // We can only have replacement methods when the target of the parent type // is inside SpacheChem.exe, and therefore is a method definition, not a reference. ReplaceMethodsOnType(decoyType, targetType, enabledPatches); if (decoyType.IsEnum) { HandleEnumFieldInjections(decoyType, enabledPatches); } } } }
private void CollectReplacements(ISymbolTranslator symbolTranslator) { CollectReplacementsForTypes(source.Types, FindTypeDefinition, symbolTranslator); }
private void CollectReplacementsForTypes(IEnumerable <TypeDefinition> typeDefinitions, TypeFinder typeFinder, ISymbolTranslator symbolTranslator) { foreach (KeyValuePair <TypeDefinition, CustomAttribute> typePair in FindAnnotated(typeDefinitions, "DecoyAttribute")) { TypeDefinition type = typePair.Key; CustomAttribute decoyAttribute = typePair.Value; string @namespace = GetAttributeFieldValue(decoyAttribute, "namespace", ""); string scrambledName = (string)decoyAttribute.ConstructorArguments[0].Value; string translatedScrambledName = symbolTranslator.TranslateType(scrambledName); TypeDefinition targetType = typeFinder(@namespace, translatedScrambledName); typeReplacements.Add(type.FullName, target.ImportReference(targetType)); if (type.GenericParameters.Count > 0) { Dictionary <string, GenericParameter> genericReplacementsForThisType = new Dictionary <string, GenericParameter>(); for (int i = 0; i < type.GenericParameters.Count; i++) { genericReplacementsForThisType.Add(type.GenericParameters[i].FullName, targetType.GenericParameters[i]); } genericParameterReplacements.Add(type.FullName, genericReplacementsForThisType); } CollectMethodReplacementsInType(type, targetType, symbolTranslator.GetMethodTranslator(scrambledName)); CollectFieldReplacementsInType(type, targetType, symbolTranslator.GetFieldTranslator(scrambledName)); // Recurse for nested types. CollectReplacementsForTypes(type.NestedTypes, (dummy, typeName) => targetType.NestedTypes.First(t => t.Name == typeName), symbolTranslator.GetTranslatorForNestedTypes(scrambledName)); } }