internal static Assembly LoadAssembly(string filePath, bool forceReload) { Assembly[] assemblyArray; if (!forceReload && !SharedUtil.IsEmpty((ICollection)(assemblyArray = AppDomain.CurrentDomain.GetAssemblies()))) { foreach (Assembly assembly in assemblyArray) { if (((assembly != null) && !(assembly is AssemblyBuilder)) && (!SharedUtil.IsEmpty(assembly.CodeBase) && IOUtil.PathEquals(assembly.CodeBase, filePath))) { return(assembly); } } } lock (LoadedAssemblies.SyncRoot) { if (forceReload || !LoadedAssemblies.ContainsKey(filePath = IOUtil.NormalizePath(filePath))) { byte[] buffer; using (FileStream stream = new FileStream(filePath, FileMode.Open, FileAccess.Read, FileShare.Read)) { buffer = new byte[stream.Length]; using (MemoryStream stream2 = new MemoryStream(buffer, true)) { IOUtil.CopyStream(stream, stream2); } } LoadedAssemblies[filePath] = Assembly.Load(buffer); } return(LoadedAssemblies[filePath] as Assembly); } }
public static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { AssemblyName assemblyName = new AssemblyName(args.Name); if (LoadedAssemblies.ContainsKey(assemblyName.Name)) { return LoadedAssemblies[assemblyName.Name]; } else { return null; } }
public void ConfigureServices(IServiceCollection serviceCollection) { Dictionary <Assembly, List <Plugin> > assemblies = new Dictionary <Assembly, List <Plugin> >(); foreach (var grouped in PluginConstructors.Where(x => typeof(IServiceHolder).IsAssignableFrom(x.Type)).GroupBy(x => x.Type.Assembly).ToArray()) { List <Plugin> assemblyInstances = new List <Plugin>(); foreach (var constructor in grouped) { if (constructor.RequiresServices) { Log.Warn($"Could not configure plugin as ServiceHolder. IServiceHolder implementations require an empty Constructor! (Type: {constructor.Type})"); continue; } if (CreateInstance(constructor, out Plugin instance, assemblies)) { PluginContainer.RegisterSingleton(instance.GetType(), instance); IServiceHolder serviceHolder = instance as IServiceHolder; serviceHolder?.ConfigureServices(serviceCollection); // pluginInstances++; assemblyInstances.Add(instance); //serviceCollection.AddSingleton(constructor.Type, instance); } PluginConstructors.Remove(constructor); } if (!assemblies.ContainsKey(grouped.Key)) { assemblies.Add(grouped.Key, assemblyInstances); } else { assemblies[grouped.Key].AddRange(assemblyInstances); } //PluginConstructors.Remove(constructor); } 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)); } } }
private void ResolveDenpendency(Assembly assembly) { if (LoadedAssemblies == null) { LoadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToDictionary(m => GetAssemblyNameVersion(m.GetName())); } string nameVersion = GetAssemblyNameVersion(assembly.GetName()); if (!LoadedAssemblies.ContainsKey(nameVersion)) { LoadedAssemblies.Add(nameVersion, assembly); } List <Assembly> dependencies = new List <Assembly>(); DependencyAssemblyResolver dependencyAssemblyResolver = new DependencyAssemblyResolver(Path.GetDirectoryName(assembly.Location)); foreach (var item in dependencyAssemblyResolver.ResolveAssemblyPaths()) { AssemblyName assemblyName = AssemblyName.GetAssemblyName(item); string assemblyNameVersion = GetAssemblyNameVersion(assemblyName); if (!LoadedAssemblies.ContainsKey(assemblyNameVersion)) { Assembly assemblyDep = AssemblyLoadContext.Default.LoadFromAssemblyPath(item); DependencyAssemblies.Add(assemblyDep); LoadedAssemblies.Add(assemblyNameVersion, assemblyDep); dependencies.Add(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, Dependencies = dependencies, CurrentPluginPath = CurrentPath }; } } if (plugin != null) { PluginActivtor.LoadedPlugins.Add(plugin); } }
public AssetTypeValueField GetMonoBaseField(AssetContainer cont, string managedPath) { var file = cont.FileInstance.file; var item = cont.Item; var baseTemp = new AssetTypeTemplateField(); baseTemp.FromClassDatabase(Am.classFile, AssetHelper.FindAssetClassByID(Am.classFile, item.TypeID), 0); var mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, item.Position); var scriptIndex = item.MonoID; if (scriptIndex != 0xFFFF) { var monoScriptCont = GetAssetContainer(mainAti.GetBaseField().Get("m_Script")); if (monoScriptCont == null) { return(null); } var scriptBaseField = monoScriptCont.TypeInstance.GetBaseField(); var scriptName = scriptBaseField.Get("m_Name").GetValue().AsString(); var scriptNamespace = scriptBaseField.Get("m_Namespace").GetValue().AsString(); var assemblyName = scriptBaseField.Get("m_AssemblyName").GetValue().AsString(); var assemblyPath = Path.Combine(managedPath, assemblyName); if (scriptNamespace != string.Empty) { scriptName = scriptNamespace + "." + scriptName; } if (File.Exists(assemblyPath)) { if (!LoadedAssemblies.ContainsKey(assemblyName)) { LoadedAssemblies.Add(assemblyName, MonoDeserializer.GetAssemblyWithDependencies(assemblyPath)); } var asmDef = LoadedAssemblies[assemblyName]; var mc = new MonoDeserializer(); mc.Read(scriptName, asmDef, file.header.format); var monoTemplateFields = mc.children; var templateField = baseTemp.children.Concat(monoTemplateFields).ToArray(); baseTemp.children = templateField; baseTemp.childrenCount = baseTemp.children.Length; mainAti = new AssetTypeInstance(baseTemp, cont.FileReader, item.Position); } } return(mainAti.GetBaseField()); }
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(); }
/// <summary> /// Gets the <see cref="Assembly"/> Indexed corresponding to the Loaded /// <paramref name="path"/> according to the <paramref name="comparisonType"/>. Assume /// that <see cref="AddDependency(string)"/> was invoked prior to Indexing the Path. /// Returns the corresponding <see cref="Assembly"/> Reference from /// <see cref="AdditionalReferencePaths"/> when loaded context fails. /// </summary> /// <param name="path">We are interested in identifying the Resolved or Augmented Path.</param> /// <param name="comparisonType">Overriding the default <see cref="StringComparison"/> is allowed.</param> /// <returns></returns> public Assembly this[string path, StringComparison comparisonType] { get { // TODO: TBD: we could potentially instruct a search heuristic to search based on Equals, or possible also Containing... Assembly GetAdditionalReference() { // TODO: TBD: should these be `augmenting´ the normally added dependencies? // TODO: TBD: or should these be fed into the normally resolved dependency context? // TODO: TBD: may capture a default comparison type applicable over the range of questions... i.e. OrdinalIgnoreCase var chosen = AdditionalReferencePaths.SingleOrDefault( x => !IsNullOrEmpty(x) && GetFileName(x).Equals(GetFileName(path), comparisonType) ); return(!IsNullOrEmpty(chosen) && File.Exists(chosen) ? Assembly.LoadFile(GetFullPath(chosen)) : null); } return(LoadedAssemblies.ContainsKey(path) ? LoadedAssemblies[path] : GetAdditionalReference()); } }
/// <summary> /// The constructor of the Assembly Resolver /// </summary> /// <param name="applicationConfig">ApplicationConfig</param> public AssemblyResolver(ApplicationConfig applicationConfig) { _applicationConfig = applicationConfig; // setup the regex var regexExtensions = string.Join("|", applicationConfig.Extensions.Select(e => e.Replace(".", @"\."))); _assemblyResourceNameRegex = new Regex($@"^(costura\.)*(?<assembly>.*)({regexExtensions})$", RegexOptions.Compiled | RegexOptions.IgnoreCase); _assemblyFilenameRegex = new Regex($@".*\\(?<assembly>.*)({regexExtensions})$", RegexOptions.Compiled | RegexOptions.IgnoreCase); Resources = new ManifestResources(simpleAssemblyName => LoadedAssemblies.ContainsKey(simpleAssemblyName) ? LoadedAssemblies[simpleAssemblyName] : null); foreach (var loadedAssembly in AppDomain.CurrentDomain.GetAssemblies()) { LoadedAssemblies[loadedAssembly.GetName().Name] = loadedAssembly; } // Register assembly loading AppDomain.CurrentDomain.AssemblyLoad += AssemblyLoad; // Register assembly resolving AppDomain.CurrentDomain.AssemblyResolve += AssemblyResolve; AppDomain.CurrentDomain.ProcessExit += (sender, args) => RemoveCopiedAssemblies(); ScanForAssemblies(); }
//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> /// This is called when a new assembly is loaded, we need to know this /// </summary> /// <param name="sender">object</param> /// <param name="args">AssemblyLoadEventArgs</param> private void AssemblyLoad(object sender, AssemblyLoadEventArgs args) { var loadedAssembly = args.LoadedAssembly; var assemblyName = loadedAssembly.GetName().Name; if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loaded {0}", assemblyName); } LoadedAssemblies[assemblyName] = loadedAssembly; if (!_applicationConfig.ScanForEmbeddedAssemblies) { return; } // Ignore resource checking on certain assemblies if (AssembliesToIgnore.IsMatch(assemblyName)) { return; } string[] resources; try { resources = Resources.GetCachedManifestResourceNames(loadedAssembly); } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't retrieve resources from {0}", loadedAssembly.GetName().Name); return; } foreach (var resource in resources) { var resourceMatch = _assemblyResourceNameRegex.Match(resource); if (!resourceMatch.Success) { continue; } var embeddedAssemblyName = resourceMatch.Groups["assembly"].Value; if (LoadedAssemblies.ContainsKey(embeddedAssemblyName)) { // Ignoring already loaded assembly, as we cannot unload. continue; } var newAssemblyLocation = new AssemblyLocationInformation(embeddedAssemblyName, loadedAssembly, resource); if (AvailableAssemblies.TryGetValue(embeddedAssemblyName, out var availableAssemblyLocationInformation)) { if (availableAssemblyLocationInformation.FileDate > newAssemblyLocation.FileDate) { continue; } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Detected additional assembly {0} in {1}", embeddedAssemblyName, loadedAssembly.GetName().Name); } AvailableAssemblies[embeddedAssemblyName] = newAssemblyLocation; } }
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)); } } }