private bool GetMetadataForDllMod(string dllPath, out Type[] exports, out bool isUnloadable)
    {
        exports      = DefaultExportedTypes; // Preventing heap allocation here.
        isUnloadable = false;

        var loadContext     = LoadContext.BuildModLoadContext(dllPath, true, SharedTypes, _sharedContext.Context);
        var defaultAssembly = loadContext.LoadDefaultAssembly();
        var types           = defaultAssembly.GetTypes();

        var exportsEntryPoint = types.FirstOrDefault(t => typeof(IExports).IsAssignableFrom(t) && !t.IsAbstract);

        if (exportsEntryPoint != null)
        {
            var pluginExports = (IExports)Activator.CreateInstance(exportsEntryPoint);
            var typesList     = new List <Type>();
            typesList.AddRange(pluginExports.GetTypes());
            typesList.AddRange(pluginExports.GetTypesEx(new ExportsContext()
            {
                ApplicationConfig = LoaderApi.GetAppConfig()
            }));

            var assemblies = LoadTypesIntoSharedContext(typesList);
            exports = new Type[typesList.Count];

            // Find exports in assemblies that were just loaded into the shared context.
            // If we use the ones from the other mods' ALCs, the other ALC will stay loaded
            // because we are still holding a reference to the exports.
            var assemblyToTypes = new Dictionary <Assembly, Type[]>();
            foreach (var asm in assemblies)
            {
                if (!assemblyToTypes.ContainsKey(asm))
                {
                    assemblyToTypes[asm] = asm.GetTypes();
                }
            }

            for (int x = 0; x < assemblies.Length; x++)
            {
                var target        = typesList[x];
                var assemblyTypes = assemblyToTypes[assemblies[x]];
                exports[x] = assemblyTypes.First(y => y.FullName == target.FullName);
            }
        }

        var modEntryPoint = types.FirstOrDefault(t => typeof(IModV1).IsAssignableFrom(t) && !t.IsAbstract);

        if (modEntryPoint != null)
        {
            var plugin = (IModV1)Activator.CreateInstance(modEntryPoint);
            isUnloadable = plugin.CanUnload();
        }

        loadContext.Dispose();
        return(true);
    }
Beispiel #2
0
        private ModInstance PrepareDllMod(PathTuple <ModConfig> tuple)
        {
            var modId   = tuple.Config.ModId;
            var dllPath = tuple.Config.GetDllPath(tuple.Path);

            _modIdToFolder[modId] = Path.GetFullPath(Path.GetDirectoryName(tuple.Path));

            var loadContext     = LoadContext.BuildModLoadContext(dllPath, _modIdToMetadata[modId].IsUnloadable, GetExportsForModConfig(tuple.Config), _sharedContext.Context);
            var defaultAssembly = loadContext.LoadDefaultAssembly();
            var types           = defaultAssembly.GetTypes();
            var entryPoint      = types.FirstOrDefault(t => typeof(IModV1).IsAssignableFrom(t) && !t.IsAbstract);

            // Load entrypoint.
            var plugin = (IModV1)Activator.CreateInstance(entryPoint);

            return(new ModInstance(loadContext, plugin, tuple.Config));
        }