mirror of
http://git.xinwangdao.com/cnnc-embedded-parts-detect/detect.git
synced 2025-06-24 13:34:13 +08:00
99 lines
4.3 KiB
C#
99 lines
4.3 KiB
C#
![]() |
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.IO;
|
|||
|
using System.Linq;
|
|||
|
using System.Reflection;
|
|||
|
|
|||
|
namespace WebViewControl {
|
|||
|
|
|||
|
internal class AssemblyCache {
|
|||
|
|
|||
|
private object SyncRoot { get; } = new object();
|
|||
|
|
|||
|
// We now allow to load multiple versions of the same assembly, which means that resource urls can
|
|||
|
// (optionally) specify the version. We don't force the version to be specified to maintain backwards
|
|||
|
// compatibility, and thus for each assembly name we two entries in the dictionary: with and without a version.
|
|||
|
// Note that no guarantee is provided about which version is resolved if there are multiple loaded assemblies
|
|||
|
// with the same name and no specific version is provided.
|
|||
|
// This, consumer apps are encouraged to include the version in the resource url
|
|||
|
private IDictionary<(string AssemblyName, Version AssemblyVersion), Assembly> assemblies;
|
|||
|
|
|||
|
private bool newAssembliesLoaded = true;
|
|||
|
|
|||
|
internal Assembly ResolveResourceAssembly(Uri resourceUrl, bool failOnMissingAssembly) {
|
|||
|
if (assemblies == null) {
|
|||
|
lock (SyncRoot) {
|
|||
|
if (assemblies == null) {
|
|||
|
assemblies = new Dictionary<(string, Version), Assembly>();
|
|||
|
AppDomain.CurrentDomain.AssemblyLoad += delegate { newAssembliesLoaded = true; };
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
var (assemblyName, assemblyVersion) = ResourceUrl.GetEmbeddedResourceAssemblyNameAndVersion(resourceUrl);
|
|||
|
var assembly = GetAssemblyByNameAndVersion(assemblyName, assemblyVersion);
|
|||
|
|
|||
|
if (assembly == null) {
|
|||
|
if (newAssembliesLoaded) {
|
|||
|
lock (SyncRoot) {
|
|||
|
if (newAssembliesLoaded) {
|
|||
|
// add loaded assemblies to cache
|
|||
|
newAssembliesLoaded = false;
|
|||
|
foreach (var domainAssembly in AppDomain.CurrentDomain.GetAssemblies()) {
|
|||
|
AddOrReplace(domainAssembly);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
assembly = GetAssemblyByNameAndVersion(assemblyName, assemblyVersion);
|
|||
|
if (assembly == null) {
|
|||
|
try {
|
|||
|
// try loading the assembly from a file named AssemblyName.dll (or AssemblyName-AssemblyVersion.dll if
|
|||
|
// a version was provided)
|
|||
|
var fileName = $"{assemblyName}{(assemblyVersion == null ? "" : $"-{assemblyVersion}")}.dll";
|
|||
|
var assemblyPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, fileName);
|
|||
|
assembly = AssemblyLoader.LoadAssembly(assemblyPath);
|
|||
|
} catch (IOException) {
|
|||
|
// ignore
|
|||
|
}
|
|||
|
|
|||
|
if (assembly != null) {
|
|||
|
lock (SyncRoot) {
|
|||
|
AddOrReplace(assembly);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (failOnMissingAssembly && assembly == null) {
|
|||
|
throw new InvalidOperationException("Could not find assembly for: " + resourceUrl);
|
|||
|
}
|
|||
|
return assembly;
|
|||
|
}
|
|||
|
|
|||
|
private void AddOrReplace(Assembly assembly) {
|
|||
|
var identity = assembly.GetName();
|
|||
|
var assemblyName = identity.Name;
|
|||
|
if (assemblyName == null) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
// add two entries, with and without the version.
|
|||
|
// for the null-version entry, keep the assembly with the highest version
|
|||
|
var version = identity.Version;
|
|||
|
if (!assemblies.TryGetValue((assemblyName, null), out var nullVersionAssembly) ||
|
|||
|
(nullVersionAssembly.GetName().Version is { } previousVersion && previousVersion < version)) {
|
|||
|
assemblies[(assemblyName, null)] = assembly;
|
|||
|
}
|
|||
|
assemblies[(assemblyName, version)] = assembly;
|
|||
|
}
|
|||
|
|
|||
|
private Assembly GetAssemblyByNameAndVersion(string assemblyName, Version assemblyVersion) {
|
|||
|
lock (SyncRoot) {
|
|||
|
assemblies.TryGetValue((assemblyName, assemblyVersion), out var assembly);
|
|||
|
return assembly;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|