using Ceciler.Interfaces; using Mono.Cecil; namespace Ceciler.Virtualizer; public class VirtualizerPatch : IPatcher { public void Patch(AssemblyDefinition assembly) { foreach (var typeDefinition in assembly.MainModule.Types) { foreach (var typeDefinitionMethod in typeDefinition.Methods) { if (typeDefinitionMethod == null) { continue; } if (typeDefinitionMethod.IsConstructor) { continue; } if (typeDefinitionMethod.IsFinal && typeDefinitionMethod.IsVirtual) { typeDefinitionMethod.IsFinal = false; continue; } if (typeDefinitionMethod.IsFinal) { continue; } if (typeDefinitionMethod.IsVirtual) { continue; } if (typeDefinitionMethod.IsStatic) { continue; } if (typeDefinitionMethod.IsPrivate) { continue; } if (MethodIsSerializationCallback(typeDefinitionMethod)) { continue; } typeDefinitionMethod.IsVirtual = true; typeDefinitionMethod.IsNewSlot = true; } } #if DEBUG var writerParams = new WriterParameters() { WriteSymbols = true }; assembly.Write(writerParams); #else assembly.Write(); #endif } static bool MethodIsSerializationCallback(MethodDefinition method) { return ContainsAttribute(method.CustomAttributes, "OnSerializingAttribute") || ContainsAttribute(method.CustomAttributes, "OnSerializedAttribute") || ContainsAttribute(method.CustomAttributes, "OnDeserializingAttribute") || ContainsAttribute(method.CustomAttributes, "OnDeserializedAttribute"); } public static bool ContainsAttribute( IEnumerable attributes, string attributeName ) => attributes.Any(attribute => attribute.Constructor.DeclaringType.Name == attributeName); public string Name { get { return "Virtualizer"; } } }