internal void AddFile(string file, DependencyResolutionStrategy dependencyResolutionStrategy, string searchedDirectory)
{
//Check the file is a dll
if (Path.GetExtension(file) != ".dll")
throw new ArgumentException("The filepath supplied was not a DLL library.");
//Check the file exists
if (!File.Exists(file))
throw new FileNotFoundException("The specified filepath does not exist.");
//Log
logger.Trace($"Searching '{file}' for plugins.");
// Setup assembly resolver to help find dependencies recursively in the folder heirachy of the plugin
AppDomain.CurrentDomain.AssemblyResolve += LoadFromSameFolder;
Assembly LoadFromSameFolder(object sender, ResolveEventArgs args)
{
string rootFolderPath;
if (dependencyResolutionStrategy == DependencyResolutionStrategy.RecursiveFromFile)
{
rootFolderPath = Path.GetDirectoryName(file);
}
else if (searchedDirectory != null)
{
rootFolderPath = searchedDirectory;
}
else
{
return null;
}
string assemblyPath = SearchForFile(rootFolderPath, new AssemblyName(args.Name).Name + ".dll");
if (assemblyPath == null)
return null;
return Assembly.LoadFrom(assemblyPath);
}
//Load the assembly
Assembly assembly;
try
{
assembly = Assembly.LoadFrom(Path.GetFullPath(file));
}
catch (Exception e)
{
logger.Error($"{file} could not be loaded as an exception occurred.", e);
return;
}
//Get the types in the assembly
IEnumerable<Type> enclosedTypes;
try
{
enclosedTypes = assembly.GetTypes();
}
catch (ReflectionTypeLoadException e)
{
logger.Error(
$"Failed to load one or more plugins from DLL file '{file}', see following logs for more info.\n\nIf this file is a DarkRift plugin rebuilding this plugin may help. Make sure it is built against the same .NET target as DarkRift is running and built to a compatible version ({Environment.Version}).\n\nThis exception can also occur when an unmanaged DLL is loaded by DarkRift because it is in a plugin search path. If this is the case, consider moving the unmanaged library out of any plugin search paths (https://docs.microsoft.com/en-us/dotnet/core/dependency-loading/default-probing#unmanaged-native-library-probing) or modify the plugin search path configuration to avoid discovering the library (e.g. reference individual DLL files instead of the containing directory).",
e
);
foreach (Exception loaderException in e.LoaderExceptions)
{
logger.Error("Additional exception detail from LoaderExceptions property:", loaderException);
}
// The types unable to be loaded will be null here!
enclosedTypes = e.Types.Where(t => t != null);
}
//Find the types that are plugins
foreach (Type enclosedType in enclosedTypes)
{
if (enclosedType.IsSubclassOf(typeof(PluginBase)) && !enclosedType.IsAbstract)
{
//Add the plugin
AddType(enclosedType);
}
}
// Remove resolver again
AppDomain.CurrentDomain.AssemblyResolve -= LoadFromSameFolder;
}