using System;
using System.Collections.Generic;
using System.Reflection;
using GameServiceWarden.Core.Module.Exceptions;
using GameServiceWarden.ModuleFramework;
namespace GameServiceWarden.Core.Module
{
public class ModuleLoader //Gateway
{
///
/// Loads an extension module.
///
/// The path to the module.
/// An from the given module.
/// When the module requested to be loaded does not contain any public classes.
public IEnumerable LoadModules(string path)
{
return instantiateServiceable(loadAssembly(path));
}
///
/// Loads all module for each given path to modules file.
///
/// The paths to load modules for.
/// A where the key is a that is the associated path.
public Dictionary> LoadAllModules(IEnumerable paths)
{
Dictionary> res = new Dictionary>();
foreach (string path in paths)
{
res.Add(path, LoadModules(path));
}
return res;
}
private Assembly loadAssembly(string path)
{
ModuleLoadContext moduleLoadContext = new ModuleLoadContext(path);
return moduleLoadContext.LoadFromAssemblyPath(path);
}
private IEnumerable instantiateServiceable(Assembly assembly)
{
int serviceableCount = 0;
foreach (Type type in assembly.GetExportedTypes())
{
if (typeof(IServiceModule).IsAssignableFrom(type))
{
IServiceModule res = Activator.CreateInstance(type) as IServiceModule;
if (res != null)
{
serviceableCount++;
yield return res;
}
}
}
if (serviceableCount == 0)
{
List typeNames = new List();
foreach (Type type in assembly.GetExportedTypes())
{
typeNames.Add(type.FullName);
}
string types = String.Join(',', typeNames);
throw new ModuleLoadException(
$"No public classes in {assembly} from {assembly.Location} implemented {typeof(IService).FullName}." +
$"Detected types: {types}");
}
}
}
}