mirror of
https://github.com/fergalmoran/DnsServer.git
synced 2025-12-22 09:29:50 +00:00
DnsApplicationAssemblyLoadContext: updated implementation to load app based on the dependencies json file.
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
Technitium DNS Server
|
||||
Copyright (C) 2024 Shreyas Zare (shreyas@technitium.com)
|
||||
Copyright (C) 2025 Shreyas Zare (shreyas@technitium.com)
|
||||
|
||||
This program is free software: you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@@ -31,8 +31,6 @@ namespace DnsServerCore.Dns.Applications
|
||||
{
|
||||
#region variables
|
||||
|
||||
readonly static Type _dnsApplicationInterface = typeof(IDnsApplication);
|
||||
|
||||
readonly IDnsServer _dnsServer;
|
||||
|
||||
readonly List<Assembly> _appAssemblies;
|
||||
@@ -63,64 +61,18 @@ namespace DnsServerCore.Dns.Applications
|
||||
}
|
||||
};
|
||||
|
||||
Resolving += delegate (AssemblyLoadContext currentContext, AssemblyName requiredAssembly)
|
||||
{
|
||||
string requiredAssemblyName = requiredAssembly.Name;
|
||||
|
||||
foreach (Assembly loadedAssembly in Default.Assemblies)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loadedAssembly.Location))
|
||||
{
|
||||
if (requiredAssemblyName.Equals(Path.GetFileNameWithoutExtension(loadedAssembly.Location), StringComparison.OrdinalIgnoreCase))
|
||||
return loadedAssembly;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (requiredAssemblyName.Equals(loadedAssembly.GetName().Name, StringComparison.OrdinalIgnoreCase))
|
||||
return loadedAssembly;
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
|
||||
//load all app assemblies
|
||||
IEnumerable<Assembly> loadedAssemblies = Default.Assemblies;
|
||||
Dictionary<string, Assembly> appAssemblies = new Dictionary<string, Assembly>();
|
||||
|
||||
foreach (string dllFile in Directory.GetFiles(_dnsServer.ApplicationFolder, "*.dll", SearchOption.TopDirectoryOnly))
|
||||
foreach (string depsFile in Directory.GetFiles(_dnsServer.ApplicationFolder, "*.deps.json", SearchOption.TopDirectoryOnly))
|
||||
{
|
||||
string dllFileName = Path.GetFileNameWithoutExtension(dllFile);
|
||||
|
||||
bool isLoaded = false;
|
||||
|
||||
foreach (Assembly loadedAssembly in loadedAssemblies)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(loadedAssembly.Location))
|
||||
{
|
||||
if (dllFileName.Equals(Path.GetFileNameWithoutExtension(loadedAssembly.Location), StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (dllFileName.Equals(loadedAssembly.GetName().Name, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
isLoaded = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (isLoaded)
|
||||
continue;
|
||||
string dllFileName = Path.GetFileNameWithoutExtension(Path.GetFileNameWithoutExtension(depsFile));
|
||||
string dllFile = Path.Combine(_dnsServer.ApplicationFolder, dllFileName + ".dll");
|
||||
|
||||
try
|
||||
{
|
||||
Assembly appAssembly;
|
||||
string pdbFile = Path.Combine(_dnsServer.ApplicationFolder, Path.GetFileNameWithoutExtension(dllFile) + ".pdb");
|
||||
string pdbFile = Path.Combine(_dnsServer.ApplicationFolder, dllFileName + ".pdb");
|
||||
|
||||
if (File.Exists(pdbFile))
|
||||
{
|
||||
@@ -141,6 +93,9 @@ namespace DnsServerCore.Dns.Applications
|
||||
}
|
||||
|
||||
appAssemblies.Add(dllFile, appAssembly);
|
||||
|
||||
if (_dependencyResolver is null)
|
||||
_dependencyResolver = new AssemblyDependencyResolver(dllFile);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
@@ -148,33 +103,6 @@ namespace DnsServerCore.Dns.Applications
|
||||
}
|
||||
}
|
||||
|
||||
//init assembly dependency resolver for main app dll
|
||||
foreach (KeyValuePair<string, Assembly> appAssembly in appAssemblies)
|
||||
{
|
||||
bool isMainAssembly = false;
|
||||
|
||||
foreach (Type classType in appAssembly.Value.ExportedTypes)
|
||||
{
|
||||
foreach (Type interfaceType in classType.GetInterfaces())
|
||||
{
|
||||
if (interfaceType == _dnsApplicationInterface)
|
||||
{
|
||||
isMainAssembly = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (isMainAssembly)
|
||||
break;
|
||||
}
|
||||
|
||||
if (isMainAssembly)
|
||||
{
|
||||
_dependencyResolver = new AssemblyDependencyResolver(appAssembly.Key);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
_appAssemblies = new List<Assembly>(appAssemblies.Values);
|
||||
}
|
||||
|
||||
@@ -184,6 +112,19 @@ namespace DnsServerCore.Dns.Applications
|
||||
|
||||
protected override Assembly Load(AssemblyName assemblyName)
|
||||
{
|
||||
if (_dependencyResolver is not null)
|
||||
{
|
||||
string resolvedPath = _dependencyResolver.ResolveAssemblyToPath(assemblyName);
|
||||
if (!string.IsNullOrEmpty(resolvedPath) && File.Exists(resolvedPath))
|
||||
return LoadFromAssemblyPath(resolvedPath);
|
||||
}
|
||||
|
||||
foreach (Assembly loadedAssembly in Default.Assemblies)
|
||||
{
|
||||
if (assemblyName.FullName == loadedAssembly.GetName().FullName)
|
||||
return loadedAssembly;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -256,6 +197,9 @@ namespace DnsServerCore.Dns.Applications
|
||||
if (!_loadedUnmanagedDlls.TryGetValue(unmanagedDllPath.ToLowerInvariant(), out IntPtr value))
|
||||
{
|
||||
//load the unmanaged DLL
|
||||
|
||||
if (RuntimeInformation.IsOSPlatform(OSPlatform.Windows))
|
||||
{
|
||||
//copy unmanaged dll into temp file for loading to allow uninstalling/updating app at runtime.
|
||||
string tempPath = Path.GetTempFileName();
|
||||
|
||||
@@ -270,6 +214,12 @@ namespace DnsServerCore.Dns.Applications
|
||||
_unmanagedDllTempPaths.Add(tempPath);
|
||||
|
||||
value = LoadUnmanagedDllFromPath(tempPath);
|
||||
}
|
||||
else
|
||||
{
|
||||
value = LoadUnmanagedDllFromPath(unmanagedDllPath);
|
||||
}
|
||||
|
||||
_loadedUnmanagedDlls.Add(unmanagedDllPath.ToLowerInvariant(), value);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user