Ejemplo n.º 1
0
        private DependencyGraph(IList <T> mods, Func <T, string> modNameGetter)
        {
            int size = mods.Count;

            vertices = new Vertex[size];
            IDictionary <string, Vertex> nameLookup = new Dictionary <string, Vertex>(size);

            // Create a vertex in the dependency graph for each mod to load
            for (int i = 0; i < size; ++i)
            {
                Assembly modAssembly = mods[i].Assembly;
                string   modName     = modNameGetter(mods[i]);

                Vertex modVertex = new Vertex(i, mods[i], modName);
                vertices[i] = modVertex;
                nameLookup[modAssembly.GetName().Name] = modVertex;
            }

            // Add an edge for each dependency between mods
            IDictionary <string, IList <AssemblyName> > modsWithMissingDeps = new SortedDictionary <string, IList <AssemblyName> >();
            List <AssemblyName> missingDependencies  = new List <AssemblyName>();
            HashSet <string>    optionalDependencies = new HashSet <string>();

            foreach (Vertex modVertex in vertices)
            {
                Assembly modAssembly = modVertex.mod.Assembly;
                missingDependencies.Clear();
                optionalDependencies.Clear();

                MelonOptionalDependenciesAttribute optionals = (MelonOptionalDependenciesAttribute)Attribute.GetCustomAttribute(modAssembly, typeof(MelonOptionalDependenciesAttribute));
                if (optionals != null && optionals.AssemblyNames != null)
                {
                    optionalDependencies.UnionWith(optionals.AssemblyNames);
                }

                foreach (AssemblyName dependency in modAssembly.GetReferencedAssemblies())
                {
                    if (nameLookup.TryGetValue(dependency.Name, out Vertex dependencyVertex))
                    {
                        modVertex.dependencies.Add(dependencyVertex);
                        dependencyVertex.dependents.Add(modVertex);
                    }
                    else if (!TryLoad(dependency) && !optionalDependencies.Contains(dependency.Name))
                    {
                        missingDependencies.Add(dependency);
                    }
                }

                if (missingDependencies.Count > 0)
                {
                    // modVertex.skipLoading = true;
                    modsWithMissingDeps.Add(modNameGetter(modVertex.mod), missingDependencies.ToArray());
                }
            }

            if (modsWithMissingDeps.Count > 0)
            {
                // Some mods are missing dependencies. Don't load these mods and show an error message
                MelonLogger.LogWarning(BuildMissingDependencyMessage(modsWithMissingDeps));
            }
        }