/// <summary> /// Add assemblies at runtime to the package. Does not load the assembly into the node library. /// If the package is already present in LoadedAssemblies, this will mutate it's IsNodeLibrary property. /// </summary> /// <param name="assems">A list of assemblies</param> internal void AddAssemblies(IEnumerable <PackageAssembly> assems) { foreach (var assem in assems) { var existingAssem = LoadedAssemblies.FirstOrDefault(x => x.Assembly.GetName().Name == assem.Assembly.GetName().Name); if (existingAssem != null) { existingAssem.IsNodeLibrary = assem.IsNodeLibrary; } else { LoadedAssemblies.Add(assem); } } }
public AssetTypeValueField GetConcatMonoBaseField(AssetContainer cont, string managedPath) { AssetsFile file = cont.FileInstance.file; AssetTypeTemplateField baseTemp = new AssetTypeTemplateField(); baseTemp.FromClassDatabase(am.classFile, AssetHelper.FindAssetClassByID(am.classFile, cont.ClassId), 0); AssetTypeInstance mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, cont.FilePosition); ushort scriptIndex = cont.MonoId; if (scriptIndex != 0xFFFF) { AssetContainer monoScriptCont = GetAssetContainer(cont.FileInstance, mainAti.GetBaseField().Get("m_Script"), false); if (monoScriptCont == null) return null; AssetTypeValueField scriptBaseField = monoScriptCont.TypeInstance.GetBaseField(); string scriptName = scriptBaseField.Get("m_Name").GetValue().AsString(); string scriptNamespace = scriptBaseField.Get("m_Namespace").GetValue().AsString(); string assemblyName = scriptBaseField.Get("m_AssemblyName").GetValue().AsString(); string assemblyPath = Path.Combine(managedPath, assemblyName); if (scriptNamespace != string.Empty) scriptName = scriptNamespace + "." + scriptName; if (File.Exists(assemblyPath)) { AssemblyDefinition asmDef; if (!LoadedAssemblies.ContainsKey(assemblyName)) { LoadedAssemblies.Add(assemblyName, MonoDeserializer.GetAssemblyWithDependencies(assemblyPath)); } asmDef = LoadedAssemblies[assemblyName]; MonoDeserializer mc = new MonoDeserializer(); mc.Read(scriptName, asmDef, file.header.format); List<AssetTypeTemplateField> monoTemplateFields = mc.children; AssetTypeTemplateField[] templateField = baseTemp.children.Concat(monoTemplateFields).ToArray(); baseTemp.children = templateField; baseTemp.childrenCount = baseTemp.children.Length; mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, cont.FilePosition); } } return mainAti.GetBaseField(); }
private void LoadAssemblies(IEnumerable <string> paths, IEnumerable <string> skipPatterns) { foreach (var path in paths) { if (skipPatterns != null && CheckPattern(skipPatterns, path)) { continue; } try { var asmCat = new AssemblyCatalog(path, GlobalRegistrationBuilder.Builder); // Force MEF to load the plugin and figure out if there are any exports // good assemblies will not throw the RTLE exception and can be added to the catalog if (asmCat.Parts.Any()) { if (CheckAlreadyLoaded(path)) { continue; } _catalog.Catalogs.Add(asmCat); LoadedAssemblies.Add(path); } } catch (ReflectionTypeLoadException e) { var typesStringBuilder = new StringBuilder(); foreach (var type in e.Types) { typesStringBuilder.Append(type); } _logger.WarnFormat("Could not load assembly '{0}' . Depending types: {1}", e, typesStringBuilder); foreach (var ex in e.LoaderExceptions) { _logger.WarnFormat("LoaderException: '{0}'", ex); } } } }
/// <summary> /// Enumerates all assemblies in the package /// </summary> /// <returns>The list of all node library assemblies</returns> internal IEnumerable <PackageAssembly> EnumerateAssembliesInBinDirectory() { var assemblies = new List <PackageAssembly>(); if (!Directory.Exists(BinaryDirectory)) { return(assemblies); } // Use the pkg header to determine which assemblies to load and prevent multiple enumeration // In earlier packages, this field could be null, which is correctly handled by IsNodeLibrary var nodeLibraries = Header.node_libraries; foreach (var assemFile in (new System.IO.DirectoryInfo(BinaryDirectory)).EnumerateFiles("*.dll")) { Assembly assem; // dll files may be un-managed, skip those var result = PackageLoader.TryLoadFrom(assemFile.FullName, out assem); if (result) { // IsNodeLibrary may fail, we store the warnings here and then show IList <ILogMessage> warnings = new List <ILogMessage>(); assemblies.Add(new PackageAssembly() { Assembly = assem, IsNodeLibrary = IsNodeLibrary(nodeLibraries, assem.GetName(), ref warnings) }); warnings.ToList().ForEach(this.Log); } } foreach (var assem in assemblies) { LoadedAssemblies.Add(assem); } return(assemblies); }
private Assembly HandleLoadedAssembly(Assembly assembly) { if (LoadedAssemblies.Contains(assembly)) { return(assembly); } LoadedAssemblies.Add(assembly); foreach (var dependentAssemblyname in assembly.GetReferencedAssemblies()) { Assembly dependentAssembly; try { dependentAssembly = Load(dependentAssemblyname); } catch { continue; } HandleLoadedAssembly(dependentAssembly); } return(assembly); }
public static void Start(IEnumerable <CompilerResult> compiledScripts) { if (Running) { return; } Running = true; appDomain = AppDomain.CreateDomain("sharpyson"); appDomain.AssemblyResolve += AppDomainOnAssemblyResolve; foreach (var compiledScript in compiledScripts) { var assemblyName = AssemblyName.GetAssemblyName(compiledScript.AssemblyPath); try { if (compiledScript.AssemblyPath.EndsWith(".dll")) { appDomain.Load(assemblyName); } else { appDomain.ExecuteAssemblyByName(assemblyName); } } catch (Exception e) { Console.WriteLine(e); throw; } LoadedAssemblies.Add(assemblyName); } }
//private Assembly AssemblyResolving(AssemblyLoadContext arg1, AssemblyName arg2) //{ // if (arg2.FullName == CurrentAssembly.FullName) // { // return CurrentAssembly; // } // var deps = DependencyContext.Default; // if (deps.CompileLibraries.Any(d => d.Name == arg2.Name)) // { // return Assembly.Load(arg2); // } // foreach (var item in DependencyAssemblies) // { // if (item.FullName == arg2.FullName) // { // return item; // } // } // return null; //} private void ResolveDenpendency(Assembly assembly) { string currentName = assembly.GetName().Name; if (CompileLibraries == null) { CompileLibraries = new HashSet <string>(); foreach (var item in DependencyContext.Default.CompileLibraries) { if (!CompileLibraries.Contains(item.Name)) { CompileLibraries.Add(item.Name); } } } List <CompilationLibrary> dependencyCompilationLibrary = DependencyContext.Load(assembly) .CompileLibraries.Where(de => PluginInfos.All(m => m.Name != de.Name) && de.Name != currentName && !CompileLibraries.Contains(de.Name)) .ToList(); if (LoadedAssemblies == null) { LoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(m => m.GetName().Name); } dependencyCompilationLibrary.Each(libaray => { foreach (var item in libaray.ResolveReferencePaths(new DependencyAssemblyResolver(Path.GetDirectoryName(assembly.Location)))) { string assemblyName = AssemblyName.GetAssemblyName(item).Name; if (!LoadedAssemblies.ContainsKey(assemblyName)) { Assembly assemblyDep = AssemblyLoadContext.Default.LoadFromAssemblyPath(item); DependencyAssemblies.Add(assemblyDep); LoadedAssemblies.Add(assemblyName, assemblyDep); } } }); PluginDescriptor plugin = null; foreach (var typeInfo in assembly.DefinedTypes) { if (typeInfo.IsAbstract || typeInfo.IsInterface) { continue; } if (PluginTypeInfo.IsAssignableFrom(typeInfo)) { plugin = new PluginDescriptor { PluginType = typeInfo.AsType(), Assembly = assembly, Dependency = dependencyCompilationLibrary, CurrentPluginPath = CurrentPath }; } } if (plugin != null) { PluginActivtor.LoadedPlugins.Add(plugin); } }
/// <summary> /// Scans the specified paths for plugins & loads them into the AppDomain /// </summary> /// <param name="paths"></param> /// <exception cref="DirectoryNotFoundException"></exception> public void DiscoverPlugins(params string[] paths) { int pluginInstances = 0; paths = paths.Where(x => { if (Directory.Exists(x)) { return(true); } else { Log.Warn($"Could not load plugins from folder \"{x}\", folder does not exist!"); return(false); } }).ToArray(); foreach (var path in paths) { if (!Directory.Exists(path)) { throw new DirectoryNotFoundException("Directory not found: " + path); } } Dictionary <Assembly, string> loadedAssemblies = new Dictionary <Assembly, string>(); //List<(Assembly assembly, string path)> loadedAssemblies = new List<(Assembly assembly, string path)>(); int processed = 0; foreach (var rawPath in paths) { string path = rawPath; string[] files = Directory.GetFiles(path, "*.dll", SearchOption.AllDirectories); foreach (string file in files) { try { string filename = Path.GetFileNameWithoutExtension(file); if (!Config.GetProperty($"plugin.{filename}.enabled", true)) { Log.Info($"Not loading \"{Path.GetRelativePath(rawPath, file)}\" as it was disabled by config."); continue; } path = Path.GetDirectoryName(file); Assembly[] result; ProcessFile(path, file, out result); processed++; if (result == null) { continue; } foreach (var assembly in result) { if (!loadedAssemblies.ContainsKey(assembly)) { loadedAssemblies.Add(assembly, path); } } } catch (BadImageFormatException ex) { if (Log.IsDebugEnabled) { Log.Debug($"File is not a .NET Assembly ({file})", ex); } } catch (Exception ex) { Log.Error($"Failed loading \"{file}\"", ex); } } } Log.Info($"Loaded {loadedAssemblies.Count} assemblies from {processed} processed files."); //List<OpenPlugin> plugins = new List<OpenPlugin>(); LinkedList <PluginConstructorData> constructorDatas = new LinkedList <PluginConstructorData>(); foreach (var assembly in loadedAssemblies) { if (assembly.Key != null) { var constructors = FindPluginConstructors(assembly.Key); foreach (var constructor in constructors) { var existing = constructorDatas.FirstOrDefault(x => x.Type == constructor.Type); if (existing != null) { if (!existing.ReferencesOtherPlugin && constructor.ReferencesOtherPlugin) { var found = constructorDatas.Find(existing); if (found != null) { found.Value = constructor; continue; } } } constructorDatas.AddLast(constructor); } } } Dictionary <Assembly, List <OpenPlugin> > assemblies = new Dictionary <Assembly, List <OpenPlugin> >(); //Load all plugins that do NOT have a reference to any other plugins. foreach (var grouped in constructorDatas.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly)) { List <OpenPlugin> assemblyInstances = new List <OpenPlugin>(); foreach (var constructor in grouped) { if (CreateInstance(constructor, out OpenPlugin instance, assemblies)) { Services.RegisterSingleton(instance.GetType(), instance); pluginInstances++; assemblyInstances.Add(instance); } } if (!assemblies.ContainsKey(grouped.Key)) { assemblies.Add(grouped.Key, assemblyInstances); } else { assemblies[grouped.Key].AddRange(assemblyInstances); } } LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>(); var requiresOthers = constructorDatas.Where(x => x.ReferencesOtherPlugin).ToArray(); foreach (var grouped in requiresOthers) { var thisNode = ordered.Find(grouped); if (thisNode == null) { thisNode = ordered.AddLast(grouped); } var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray(); foreach (var otherDependency in otherPlugins) { var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency); if (found != null) { ordered.AddBefore(thisNode, found); } } } bool done = false; var current = ordered.First; do { var currentValue = current?.Value; var next = current?.Next; if (next == null || currentValue == null) { done = true; break; } if (currentValue.Requires(next.Value)) { current.Value = next.Value; next.Value = currentValue; } current = next; } while (!done); foreach (var item in ordered) { // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>(); if (Services.TryResolve(item.Type, out _)) { continue; } if (CreateInstance(item, out var instance, assemblies)) { Services.RegisterSingleton(item.Type, instance); //.Add(instance); pluginInstances++; if (!assemblies.ContainsKey(item.Type.Assembly)) { assemblies.Add(item.Type.Assembly, new List <OpenPlugin>() { instance }); } else { assemblies[item.Type.Assembly].Add(instance); } } } Log.Info($"Registered {pluginInstances} plugin instances"); foreach (var grouped in assemblies) { LoadedAssemblies.Add(grouped.Key, new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0], grouped.Key.Location)); } }
/// <summary> /// Applies patchers to all assemblies in the given directory and loads patched assemblies into memory. /// </summary> /// <param name="directory">Directory to load CLR assemblies from.</param> public void PatchAndLoad() { // First, create a copy of the assembly dictionary as the initializer can change them var assemblies = new Dictionary <string, AssemblyDefinition>(AssembliesToPatch, StringComparer.InvariantCultureIgnoreCase); // Next, initialize all the patchers foreach (var assemblyPatcher in PatcherPluginsSafe) { try { assemblyPatcher.Initializer?.Invoke(); } catch (Exception ex) { Logger.LogError($"Failed to run initializer of {assemblyPatcher.TypeName}: {ex}"); } } // Then, perform the actual patching var patchedAssemblies = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); var resolvedAssemblies = new Dictionary <string, string>(); // TODO: Maybe instead reload the assembly and repatch with other valid patchers? var invalidAssemblies = new HashSet <string>(StringComparer.InvariantCultureIgnoreCase); foreach (var assemblyPatcher in PatcherPluginsSafe) { foreach (string targetDll in assemblyPatcher.TargetDLLs()) { if (AssembliesToPatch.TryGetValue(targetDll, out var assembly) && !invalidAssemblies.Contains(targetDll)) { Logger.LogInfo($"Patching [{assembly.Name.Name}] with [{assemblyPatcher.TypeName}]"); try { assemblyPatcher.Patcher?.Invoke(ref assembly); } catch (Exception e) { Logger.LogError($"Failed to run [{assemblyPatcher.TypeName}] when patching [{assembly.Name.Name}]. This assembly will not be patched. Error: {e}"); patchedAssemblies.Remove(targetDll); invalidAssemblies.Add(targetDll); continue; } AssembliesToPatch[targetDll] = assembly; patchedAssemblies.Add(targetDll); foreach (var resolvedAss in AppDomain.CurrentDomain.GetAssemblies()) { var name = Utility.TryParseAssemblyName(resolvedAss.FullName, out var assName) ? assName.Name : resolvedAss.FullName; // Report only the first type that caused the assembly to load, because any subsequent ones can be false positives if (!resolvedAssemblies.ContainsKey(name)) { resolvedAssemblies[name] = assemblyPatcher.TypeName; } } } } } // Check if any patched assemblies have been already resolved by the CLR // If there are any, they cannot be loaded by the preloader var patchedAssemblyNames = new HashSet <string>(assemblies.Where(kv => patchedAssemblies.Contains(kv.Key)).Select(kv => kv.Value.Name.Name), StringComparer.InvariantCultureIgnoreCase); var earlyLoadAssemblies = resolvedAssemblies.Where(kv => patchedAssemblyNames.Contains(kv.Key)).ToList(); if (earlyLoadAssemblies.Count != 0) { Logger.LogWarning(new StringBuilder() .AppendLine("The following assemblies have been loaded too early and will not be patched by preloader:") .AppendLine(string.Join(Environment.NewLine, earlyLoadAssemblies.Select(kv => $"* [{kv.Key}] (first loaded by [{kv.Value}])").ToArray())) .AppendLine("Expect unexpected behavior and issues with plugins and patchers not being loaded.") .ToString()); } // Finally, load patched assemblies into memory if (ConfigDumpAssemblies.Value || ConfigLoadDumpedAssemblies.Value) { if (!Directory.Exists(DumpedAssembliesPath)) { Directory.CreateDirectory(DumpedAssembliesPath); } foreach (KeyValuePair <string, AssemblyDefinition> kv in assemblies) { string filename = kv.Key; var assembly = kv.Value; if (patchedAssemblies.Contains(filename)) { assembly.Write(Path.Combine(DumpedAssembliesPath, filename)); } } } if (ConfigBreakBeforeLoadAssemblies.Value) { Logger.LogInfo($"BepInEx is about load the following assemblies:\n{String.Join("\n", patchedAssemblies.ToArray())}"); Logger.LogInfo($"The assemblies were dumped into {DumpedAssembliesPath}"); Logger.LogInfo("Load any assemblies into the debugger, set breakpoints and continue execution."); Debugger.Break(); } foreach (var kv in assemblies) { string filename = kv.Key; var assembly = kv.Value; // Note that since we only *load* assemblies, they shouldn't trigger dependency loading // Not loading all assemblies is very important not only because of memory reasons, // but because some games *rely* on that because of messed up internal dependencies. if (patchedAssemblies.Contains(filename)) { Assembly loadedAssembly; if (ConfigLoadDumpedAssemblies.Value) { loadedAssembly = Assembly.LoadFile(Path.Combine(DumpedAssembliesPath, filename)); } else { using (var assemblyStream = new MemoryStream()) { assembly.Write(assemblyStream); loadedAssembly = Assembly.Load(assemblyStream.ToArray()); } } LoadedAssemblies.Add(filename, loadedAssembly); Logger.LogDebug($"Loaded '{assembly.FullName}' into memory"); } // Though we have to dispose of all assemblies regardless of them being patched or not assembly.Dispose(); } // Finally, run all finalizers foreach (var assemblyPatcher in PatcherPluginsSafe) { try { assemblyPatcher.Finalizer?.Invoke(); } catch (Exception ex) { Logger.LogError($"Failed to run finalizer of {assemblyPatcher.TypeName}: {ex}"); } } }
public static void RegisterAssembly(string assemblyPath) { var assembly = Assembly.LoadFrom(assemblyPath); LoadedAssemblies.Add(assembly); }
public ArchiveContext(string path, ZipArchive archive, Assembly assembly) { Path = path; Archive = archive; LoadedAssemblies.Add(assembly); }
public void LoadPlugins() { int pluginInstances = 0; Dictionary <Assembly, List <Plugin> > assemblies = new Dictionary <Assembly, List <Plugin> >(); //Load all plugins that do NOT have a reference to any other plugins. foreach (var grouped in PluginConstructors.Where(x => !x.ReferencesOtherPlugin).GroupBy(x => x.Type.Assembly).ToArray()) { List <Plugin> assemblyInstances = new List <Plugin>(); foreach (var constructor in grouped) { if (CreateInstance(constructor, out Plugin instance, assemblies)) { PluginContainer.RegisterSingleton(instance.GetType(), instance); pluginInstances++; assemblyInstances.Add(instance); } PluginConstructors.Remove(constructor); } if (!assemblies.ContainsKey(grouped.Key)) { assemblies.Add(grouped.Key, assemblyInstances); } else { assemblies[grouped.Key].AddRange(assemblyInstances); } } LinkedList <PluginConstructorData> ordered = new LinkedList <PluginConstructorData>(); var requiresOthers = PluginConstructors.Where(x => x.ReferencesOtherPlugin).ToArray(); foreach (var grouped in requiresOthers) { var thisNode = ordered.Find(grouped); if (thisNode == null) { thisNode = ordered.AddLast(grouped); } var otherPlugins = grouped.Dependencies.Where(x => x.IsPluginInstance).Select(x => x.Type).ToArray(); foreach (var otherDependency in otherPlugins) { var found = requiresOthers.FirstOrDefault(x => x.Type == otherDependency); if (found != null) { ordered.AddBefore(thisNode, found); } } } bool done = false; var current = ordered.First; do { var currentValue = current?.Value; var next = current?.Next; if (next == null || currentValue == null) { done = true; break; } if (currentValue.Requires(next.Value)) { current.Value = next.Value; next.Value = currentValue; } current = next; } while (!done); foreach (var item in ordered) { // List<OpenPlugin> assemblyInstances = new List<OpenPlugin>(); if (PluginContainer.TryResolve(item.Type, out _)) { continue; } if (CreateInstance(item, out var instance, assemblies)) { PluginContainer.RegisterSingleton(item.Type, instance); //.Add(instance); pluginInstances++; if (!assemblies.ContainsKey(item.Type.Assembly)) { assemblies.Add(item.Type.Assembly, new List <Plugin>() { instance }); } else { assemblies[item.Type.Assembly].Add(instance); } } } Log.Info($"Registered {pluginInstances} plugin instances"); foreach (var grouped in assemblies) { if (LoadedAssemblies.ContainsKey(grouped.Key)) { LoadedAssemblies[grouped.Key].PluginTypes.AddRange(grouped.Value.Select(x => x.GetType())); continue; } else { LoadedAssemblies.Add(grouped.Key, new LoadedAssembly(grouped.Key, grouped.Value.Select(x => x.GetType()), new Assembly[0], grouped.Key.Location)); } } }
internal static void Run() { JEMLogger.Log("Loading appcfg.", "APP"); AppConfig.LoadConfiguration(); if (!Directory.Exists(AssembliesDirectory)) { JEMLogger.LogError($"Assemblies directory `{AssembliesDirectory}` does not exist.", "APP"); return; } var assembliesTargets = AssembliesDirectory + JEMVar.DirectorySeparatorChar + AppConfig.Loaded.AssembliesTargetsFile; if (!File.Exists(assembliesTargets)) { JEMLogger.LogError($"File defining target assemblies `{assembliesTargets}` does not exist.", "APP"); return; } AppDomain.CurrentDomain.AssemblyResolve += (sender, args) => { JEMLogger.LogError("Failed to resolve assembly " + args.Name, "APP"); return(Assembly.LoadFrom(args.Name)); }; AssembliesNames = File.ReadAllLines(assembliesTargets); JEMLogger.Log($"{AssembliesNames.Length} target assemblies found.", "APP"); foreach (var a in AssembliesNames) { JEMLogger.Log($"\t{a}", "APP"); } Console.WriteLine(); if (Directory.Exists(DeployDirectory)) { Directory.Delete(DeployDirectory, true); } Directory.CreateDirectory(DeployDirectory); foreach (var a in AssembliesNames) { var file = AssembliesDirectory + JEMVar.DirectorySeparatorChar + a + ".dll"; AssemblyName assemblyName = null; try { assemblyName = AssemblyName.GetAssemblyName(file); } catch (Exception e) { JEMLogger.LogException(e, "APP"); } var assembly = assemblyName == null ? null : Assembly.Load(assemblyName); if (assembly == null) { JEMLogger.LogError($"Unable to load assembly `{file}`", "APP"); } else { JEMLogger.Log($"Assembly {file} loaded..", "APP"); LoadedAssemblies.Add(assembly); } } JEMLogger.Log("Generating.", "APP"); foreach (var assembly in LoadedAssemblies) { try { GenerateOffAssembly(assembly); } catch (TypeLoadException e) { Console.WriteLine(e); throw; } } }
/*public delegate void AssemblyLoadedHandler(AssemblyLoadedEventArgs args); * * public class AssemblyLoadedEventArgs * { * public Assembly Assembly { get; private set; } * * public AssemblyLoadedEventArgs(Assembly assembly) * { * Assembly = assembly; * } * } * * public event AssemblyLoadedHandler AssemblyLoaded; * * private void OnAssemblyLoaded(Assembly assem) * { * if (AssemblyLoaded != null) * { * AssemblyLoaded(new AssemblyLoadedEventArgs(assem)); * } * } */ /// <summary> /// Load all types which inherit from NodeModel whose assemblies are located in /// the bin/nodes directory. Add the types to the searchviewmodel and /// the controller's dictionaries. /// </summary> public virtual List <Type> LoadNodeModels(string folderToSearch, bool searchAppDomain) { var loadedAssembliesByPath = new Dictionary <string, Assembly>(); var loadedAssembliesByName = new Dictionary <string, Assembly>(); var allNodeAssemblies = new List <System.Reflection.Assembly>(); // cache the loaded assembly information if (searchAppDomain) { foreach ( var assembly in AppDomain.CurrentDomain.GetAssemblies()) { try { loadedAssembliesByPath[assembly.Location] = assembly; loadedAssembliesByName[assembly.FullName] = assembly; } catch { } } allNodeAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList(); } var loadedTypes = new List <Type>(); // going to look in all currently loaded assemblies for nodes, then we'll also look // in a specific folder of the resources or data folder, unsure on this path yet... string path = Application.dataPath; Debug.Log(path); path = Path.Combine(path, folderToSearch); Debug.Log(path); List <Assembly> allAssembliesinbuild = new List <Assembly>(); foreach (string dll in Directory.GetFiles(path, "*.dll")) { allAssembliesinbuild.Add(Assembly.LoadFile(dll)); } allNodeAssemblies.AddRange(allAssembliesinbuild); //iterate each assembly location foreach (var assemblyPath in allNodeAssemblies.Select(x => x.Location).ToList()) { Debug.Log("current assembly path is " + assemblyPath); //get the filename at each location and check it's not null var fn = Path.GetFileName(assemblyPath); if (fn == null) { continue; } Debug.Log("filename is " + fn); // if the assembly has already been loaded, then // skip it, otherwise cache it. if (LoadedAssemblyNames.Contains(fn)) { continue; } LoadedAssemblyNames.Add(fn); try { Assembly assembly; if (!loadedAssembliesByPath.TryGetValue(assemblyPath, out assembly)) { Debug.Log("about to load assembly from" + assemblyPath); assembly = Assembly.LoadFrom(assemblyPath); loadedAssembliesByName[assembly.GetName().Name] = assembly; loadedAssembliesByPath[assemblyPath] = assembly; } loadedTypes.AddRange(LoadNodesFromAssembly(assembly)); LoadedAssemblies.Add(assembly); //TODO possibly readd event that fires when assemlbly loaded //OnAssemblyLoaded(assembly); } catch (BadImageFormatException) { //swallow these warnings. } catch (Exception e) { Debug.LogException(e); } } //AppDomain.CurrentDomain.AssemblyResolve -= resolver; return(loadedTypes); }