示例#1
0
        /// <summary>
        /// Performs work to dispose collection objects.
        /// </summary>
        public void Dispose()
        {
            foreach (var assembly in AssembliesToPatch)
            {
                assembly.Value.Dispose();
            }

            AssembliesToPatch.Clear();

            // Clear to allow GC collection.
            PatcherPlugins.Clear();
        }
示例#2
0
        /// <summary>
        ///     Adds all patchers from all managed assemblies specified in a directory.
        /// </summary>
        /// <param name="directory">Directory to search patcher DLLs from.</param>
        public void AddPatchersFromDirectory(string directory)
        {
            if (!Directory.Exists(directory))
            {
                return;
            }

            var sortedPatchers = new SortedDictionary <string, PatcherPlugin>();

            var patchers = TypeLoader.FindPluginTypes(directory, ToPatcherPlugin);

            foreach (var keyValuePair in patchers)
            {
                var assemblyPath      = keyValuePair.Key;
                var patcherCollection = keyValuePair.Value;

                if (patcherCollection.Count == 0)
                {
                    continue;
                }

                var ass = Assembly.LoadFile(assemblyPath);

                foreach (var patcherPlugin in patcherCollection)
                {
                    try
                    {
                        var type = ass.GetType(patcherPlugin.TypeName);

                        var methods = type.GetMethods(ALL);

                        patcherPlugin.Initializer = CreateDelegate <Action>(methods.FirstOrDefault(m => m.Name.Equals("Initialize", StringComparison.InvariantCultureIgnoreCase) &&
                                                                                                   m.GetParameters().Length == 0 &&
                                                                                                   m.ReturnType == typeof(void)));

                        patcherPlugin.Finalizer = CreateDelegate <Action>(methods.FirstOrDefault(m => m.Name.Equals("Finish", StringComparison.InvariantCultureIgnoreCase) &&
                                                                                                 m.GetParameters().Length == 0 &&
                                                                                                 m.ReturnType == typeof(void)));

                        patcherPlugin.TargetDLLs = CreateDelegate <Func <IEnumerable <string> > >(type.GetProperty("TargetDLLs", ALL).GetGetMethod());

                        var patcher = methods.FirstOrDefault(m => m.Name.Equals("Patch", StringComparison.CurrentCultureIgnoreCase) &&
                                                             m.ReturnType == typeof(void) &&
                                                             m.GetParameters().Length == 1 &&
                                                             (m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition) ||
                                                              m.GetParameters()[0].ParameterType == typeof(AssemblyDefinition).MakeByRefType()));

                        patcherPlugin.Patcher = (ref AssemblyDefinition pAss) =>
                        {
                            //we do the array fuckery here to get the ref result out
                            object[] args = { pAss };

                            patcher.Invoke(null, args);

                            pAss = (AssemblyDefinition)args[0];
                        };

                        sortedPatchers.Add($"{ass.GetName().Name}/{type.FullName}", patcherPlugin);
                    }
                    catch (Exception e)
                    {
                        Logger.LogError($"Failed to load patcher [{patcherPlugin.TypeName}]: {e.Message}");
                        if (e is ReflectionTypeLoadException re)
                        {
                            Logger.LogDebug(TypeLoader.TypeLoadExceptionToString(re));
                        }
                        else
                        {
                            Logger.LogDebug(e.ToString());
                        }
                    }
                }

                var assName = ass.GetName();
                Logger.Log(patcherCollection.Any() ? LogLevel.Info : LogLevel.Debug,
                           $"Loaded {patcherCollection.Count} patcher method{(patcherCollection.Count == 1 ? "" : "s")} from [{assName.Name} {assName.Version}]");
            }

            foreach (KeyValuePair <string, PatcherPlugin> patcher in sortedPatchers)
            {
                PatcherPlugins.Add(patcher.Value);
            }
        }