Esempio n. 1
0
        /// <summary>
        /// Applies the patch described in the given PatchingManifest to the TargetAssembly.
        /// </summary>
        /// <param name="manifest">The PatchingManifest. Note that the instance will be populated with additional information (such as newly created types) during execution.</param>
        /// <param name="o"></param>
        public void PatchManifest(PatchingManifest manifest, IProgressMonitor o)
        {
            /*	The point of this method is to introduce all the patched elements in the correct order.
             *
             * Standard order of business for order between modify/remove/update:
             * 1. Remove Xs
             * 2. Create new Xs
             * 3. Update existing Xs (+ those we just created)
             */
            manifest.Specialize(TargetAssembly);
            o.TaskTitle = $"{manifest.PatchAssembly.Name.Name}";
            o.Current   = 0;
            o.Total     = 11;
            AssemblyDefinition targetAssemblyBackup = null;

            if (UseBackup)
            {
                targetAssemblyBackup = TargetAssembly.Clone();
            }

            try {
                CurrentMemberCache = manifest.CreateCache();
                //+INTRODUCE NEW TYPES
                //Declare all the new types, in the order of their nesting level (.e.g topmost types, nested types, types nested in those, etc),
                //But don't set anything that references other things, like BaseType, interfaces, custom attributes, etc.
                //Type parameters *are* added at this stage, but no constraints are specified.
                //DEPENDENCIES: None
                o.TaskText = "Introducing Types";
                IntroduceTypes(manifest.TypeActions);
                o.Current++;

                //+REMOVE EXISTING METHODS
                //Remove any methods that need removing.
                //DEPENDENCIES: Probably none
                o.TaskText = "Removing Methods";
                RemoveMethods(manifest.MethodActions);
                o.Current++;

                //+INTRODUCE NEW METHOD AND METHOD TYPE DEFINITIONS
                //Declare all the new methods and their type parameters, but do not set nything that references other types,
                //including return type, parameter types, and type parameter constraints
                //This is because method type variables must already exist.
                //This is performed now because types can reference attribute constructors that don't exist until we create them,
                //Don't set custom attributes in this stage.
                //DEPENDENCIES: Type definitions (when introduced to new types)
                o.TaskText = "Introducing Methods";
                IntroduceMethods(manifest.MethodActions);
                o.Current++;

                //+UPDATE METHOD DECLERATIONS
                //Update method declerations with parameters and return types
                //We do this separately, because a method's parameters and return types depend on that method's generic parameters
                //Don't set custom attributes in this stage though it's possible to do so.
                //This is to avoid code duplication.
                //DEPENDENCIES: Type definitions, method definitions
                o.TaskText = "Updating Type Declerations";
                UpdateMethodDeclerations(manifest.MethodActions);
                o.Current++;

                //+IMPORT ASSEMBLY/MODULE CUSTOM ATTRIBUTES
                //Add any custom attributes for things that aren't part of the method/type hierarchy, such as assemblies.
                //DEPENDENCIES: Method definitions, type definitions. (for attribute types and attribute constructors)
                o.TaskText = "Importing Assembly/Module Attributes";
                var patchingAssembly = manifest.PatchAssembly;

                //for assmebly:
                CopyCustomAttributesByImportAttribute(TargetAssembly, patchingAssembly,
                                                      patchingAssembly.GetCustomAttribute <ImportCustomAttributesAttribute>());

                //for module:
                CopyCustomAttributesByImportAttribute(TargetAssembly.MainModule, patchingAssembly.MainModule,
                                                      patchingAssembly.MainModule.GetCustomAttribute <ImportCustomAttributesAttribute>());
                o.Current++;

                //+UPDATE TYPE DEFINITIONS
                //Set the type information we didn't set in (1), according to the same order, including custom attributes.
                //When/if modifying type inheritance is allowed, this process will occur at this stage.
                //DEPENDENCIES: Type definitions (obviously), method definitions (for attribute constructors)
                o.TaskText = "Updating Type Definitions";
                UpdateTypes(manifest.TypeActions);
                o.Current++;

                //+FIELDS
                //remove/define/modify fields. This is where most enum processing happens. Custom attributes are set at this stage.
                //DEPENDENCIES: Type definitions, method definitions (for attribute constructors)
                o.TaskText = "Processing Fields";
                ClearReplacedTypes(manifest.TypeActions);
                RemoveFields(manifest.FieldActions);
                IntroduceFields(manifest.FieldActions);
                UpdateFields(manifest.FieldActions);
                o.Current++;

                //+PROPERTIES
                //Remove/define/modify properties. This doesn't change anything about methods. Custom attributes are set at this stage.
                //DEPENDENCIES: Type definitions, method definitions (attribute constructors, getter/setters)
                o.TaskText = "Processing Properties";
                RemoveProperties(manifest.PropertyActions);
                IntroduceProperties(manifest.PropertyActions);
                UpdateProperties(manifest.PropertyActions);
                o.Current++;

                //+EVENTS
                //Remove/define/modify events. This doesn't change anything about methods. Custom attributes are set at this stage.
                //DEPENENCIES: Type definitions, method definitions (attribute constructors, add/remove/invoke handlers)
                o.TaskText = "Introducing Events";
                RemoveEvents(manifest.EventActions);
                IntroduceEvents(manifest.EventActions);
                UpdateEvents(manifest.EventActions);
                o.Current++;

                //+FINALIZE METHODS, GENERATE METHOD BODIES
                //Fill/modify the bodies of all remaining methods, and also modify accessibility/attributes of existing ones.
                //Note that methods that are the source of DuplicatesBody will be resolved in their unmodified version,
                //so the modifications won't influence this functionality.
                //Custom attributes are set at this stage.
                //Also, explicit overrides (what in C# is explicit interface implementation) are specified here.
                //DEPENDENCIES: Type definitions, method definitions, method signature elements, field definitions
                o.TaskText = "Updating Method Bodies";
                UpdateMethods(manifest.MethodActions);
                o.Current++;

                //+ADD PATCHING HISTORY TO ASSEMBLY
                o.TaskText = "Updating History";
                if (EmbedHistory)
                {
                    TargetAssembly.AddPatchedByAssemblyAttribute(manifest.PatchAssembly, _assemblyHistoryIndex++, OriginalAssemblyMetadata);
                }
                o.Current++;
            }
            catch {
                if (UseBackup)
                {
                    TargetAssembly = targetAssemblyBackup;
                }
                throw;
            }
        }