/// <summary> /// This will try to resolve the requested assembly by looking into the cache /// </summary> /// <param name="sender">object</param> /// <param name="resolveEventArgs">ResolveEventArgs</param> /// <returns>Assembly</returns> private Assembly AssemblyResolve(object sender, ResolveEventArgs resolveEventArgs) { var assemblyName = new AssemblyName(resolveEventArgs.Name); // Fail fast for resolving .resources requests if (assemblyName.Name.EndsWith(".resources")) { return(null); } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Resolving {0}", assemblyName.FullName); } if (_resolving.Contains(assemblyName.Name)) { Log.Warn().WriteLine("Ignoring recursive resolve event for {0}", assemblyName.Name); return(null); } if (LoadedAssemblies.TryGetValue(assemblyName.Name, out var assemblyResult)) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Returned {0} from cache.", assemblyName.Name); } return(assemblyResult); } try { _resolving.Add(assemblyName.Name); if (!AvailableAssemblies.TryGetValue(assemblyName.Name, out var assemblyLocationInformation)) { return(null); } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Found {0} at {1}.", assemblyName.Name, assemblyLocationInformation.ToString()); } return(LoadAssembly(assemblyLocationInformation)); } finally { _resolving.Remove(assemblyName.Name); } }
/// <summary> /// Load a named assembly /// </summary> /// <param name="assemblyName">string</param> /// <returns>Assembly</returns> public Assembly LoadAssembly(string assemblyName) { // Check if the simple name can be found in the cache if (LoadedAssemblies.TryGetValue(assemblyName, out var assembly)) { Log.Info().WriteLine("Returned {0} from cache.", assemblyName); return(assembly); } if (AvailableAssemblies.TryGetValue(assemblyName, out var assemblyLocationInformation)) { return(LoadAssembly(assemblyLocationInformation)); } return(Assembly.Load(assemblyName)); }
/// <summary> /// Internally tries to retrieve a previously compiled template from cache /// if not found compiles a template into an assembly /// always returns an assembly id as a string. /// </summary> /// <param name="templateText">The text to parse</param> /// <returns>assembly id as a string or null on error</returns> protected virtual CompiledAssemblyItem GetAssemblyFromStringAndCache(string templateText) { var hash = templateText.GetHashCode(); CompiledAssemblyItem item; LoadedAssemblies.TryGetValue(hash, out item); string assemblyId = null; // Check for cached instance if (item != null) { assemblyId = item.AssemblyId; } else { item = new CompiledAssemblyItem(); } // No cached instance - create assembly and cache if (assemblyId == null) { var safeClassName = GetSafeClassName(null); using (var reader = new StringReader(templateText)) { var refAssemblies = ReferencedAssemblies.ToArray(); assemblyId = Engine.ParseAndCompileTemplate(refAssemblies, reader, GeneratedNamespace, safeClassName); } if (assemblyId == null) { ErrorMessage = Engine.ErrorMessage; return(null); } item.AssemblyId = assemblyId; item.CompileTimeUtc = DateTime.UtcNow; item.SafeClassName = safeClassName; LoadedAssemblies[hash] = item; } return(item); }
/// <summary> /// Load an assembly from the specified location /// </summary> /// <param name="assemblyLocationInformation">AssemblyLocationInformation</param> /// <returns>Assembly</returns> public Assembly LoadAssembly(AssemblyLocationInformation assemblyLocationInformation) { // Check if the simple name can be found in the cache if (LoadedAssemblies.TryGetValue(assemblyLocationInformation.Name, out var assembly)) { if (Log.IsInfoEnabled()) { Log.Info().WriteLine("Returned {0} from cache.", assemblyLocationInformation.Name); } return(assembly); } if (assemblyLocationInformation.IsEmbedded) { return(LoadEmbeddedAssembly(assemblyLocationInformation)); } // Load from file return(LoadFromFile(assemblyLocationInformation)); }
/// <summary> /// Load an assembly via a file, this used via Assembly.Load or Assembly.LoadFrom depending on where the file is or can be stored /// </summary> /// <param name="additionalInformation">AssemblyLocationInformation used for some decisions</param> /// <returns>Assembly</returns> private Assembly LoadFromFile(AssemblyLocationInformation additionalInformation) { // Get the assembly name from the file var assemblyName = AssemblyName.GetAssemblyName(additionalInformation.Filename); // Check the cache again, this time with the "real" name if (LoadedAssemblies.TryGetValue(assemblyName.Name, out var assembly)) { if (Log.IsInfoEnabled()) { Log.Info().WriteLine("Returned {0} from cache.", assemblyName.Name); } return(assembly); } var destination = $@"{FileLocations.AddonsLocation}\{assemblyName.Name}.dll"; var destinationIsNotSource = !destination.Equals(additionalInformation.Filename, StringComparison.OrdinalIgnoreCase); if (Log.IsDebugEnabled() && !destinationIsNotSource) { Log.Debug().WriteLine("Skipping copy, as destination and source would be the same."); } if (_applicationConfig.CopyAssembliesToProbingPath && FileLocations.AddonsLocation != null && destinationIsNotSource) { try { if (ShouldWrite(additionalInformation, destination)) { if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Creating a copy of {0} to {1}, solving potential context loading issues.", additionalInformation.Filename, destination); } File.Copy(additionalInformation.Filename, destination); // Register delete on exit, this is done by calling a command _assembliesToDeleteAtExit.Add(destination); } // Load via the assembly name, it's not inside the probing path assembly = Assembly.Load(assemblyName); if (assembly != null) { return(assembly); } } catch (Exception ex) { Log.Warn().WriteLine(ex, "Couldn't create a copy of {0} to {1}.", additionalInformation.Filename, destination); } } if (Log.IsVerboseEnabled()) { Log.Verbose().WriteLine("Loading {0} from {1}.", additionalInformation.Name, additionalInformation.Filename); } try { return(Assembly.LoadFrom(additionalInformation.Filename)); } catch (Exception ex) { Log.Error().WriteLine(ex, "Couldn't load assembly from file {0}", additionalInformation.Filename); } return(null); }