C# 无法在netcoreapp中加载具有特定于平台的dll的NuGet dll
我无法使用netcoreapp中提供的ICompilationAssemblyResolver从其nuget包加载C# 无法在netcoreapp中加载具有特定于平台的dll的NuGet dll,c#,nuget,.net-standard,C#,Nuget,.net Standard,我无法使用netcoreapp中提供的ICompilationAssemblyResolver从其nuget包加载System.Data.Clientdll。程序集解析的大部分是从中借用的,在大多数情况下都非常有效。看起来是这样的: internal sealed class AssemblyResolver : IDisposable { private readonly ICompilationAssemblyResolver assemblyResolver; privat
System.Data.Client
dll。程序集解析的大部分是从中借用的,在大多数情况下都非常有效。看起来是这样的:
internal sealed class AssemblyResolver : IDisposable
{
private readonly ICompilationAssemblyResolver assemblyResolver;
private readonly DependencyContext dependencyContext;
private readonly AssemblyLoadContext loadContext;
public AssemblyResolver(string path)
{
this.Assembly = AssemblyLoadContext.Default.LoadFromAssemblyPath(path);
this.dependencyContext = DependencyContext.Load(this.Assembly);
this.assemblyResolver = new CompositeCompilationAssemblyResolver(new ICompilationAssemblyResolver[]
{
new AppBaseCompilationAssemblyResolver(Path.GetDirectoryName(path)),
new ReferenceAssemblyPathResolver(),
new PackageCompilationAssemblyResolver()
});
this.loadContext = AssemblyLoadContext.GetLoadContext(this.Assembly);
this.loadContext.Resolving += OnResolving;
}
public Assembly Assembly { get; }
public void Dispose()
{
this.loadContext.Resolving -= this.OnResolving;
}
private Assembly OnResolving(AssemblyLoadContext context, AssemblyName name)
{
bool NamesMatch(RuntimeLibrary runtime)
{
return string.Equals(runtime.Name, name.Name, StringComparison.OrdinalIgnoreCase);
}
RuntimeLibrary library =
this.dependencyContext.RuntimeLibraries.FirstOrDefault(NamesMatch);
if (library != null)
{
var wrapper = new CompilationLibrary(
library.Type,
library.Name,
library.Version,
library.Hash,
library.RuntimeAssemblyGroups.SelectMany(g => g.AssetPaths),
library.Dependencies,
library.Serviceable);
var assemblies = new List<string>();
this.assemblyResolver.TryResolveAssemblyPaths(wrapper, assemblies);
if (assemblies.Count > 0)
{
return this.loadContext.LoadFromAssemblyPath(assemblies[0]);
}
}
return null;
}
}
我不知道为什么在我指定了4.3.0的情况下它会尝试加载4.1.0,但我认为这有点冒险。我怀疑packagecompilementassemblyresolver
仅在lib
文件夹下查找,并且所讨论的包没有用于netstandard的包。但是,对于特定的运行时,它确实有一个:
有了这些信息,我创建了一个非常粗糙的AssemblyLoader,它在runtimes文件夹下查找nuget包,我能够加载dll并按预期运行我的程序
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
namespace Loader
{
public class CrudeCompilationAssemblyResolver : ICompilationAssemblyResolver
{
private readonly string[] _nugetPackageDirectories;
public CrudeCompilationAssemblyResolver()
{
var basePath = Environment.GetEnvironmentVariable("HOME");
var defaultPath = Path.Combine(basePath, ".nuget", "packages");
_nugetPackageDirectories = new [] { defaultPath };
}
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (_nugetPackageDirectories == null || _nugetPackageDirectories.Length == 0 || !string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
return false;
}
foreach (var directory in _nugetPackageDirectories)
{
string packagePath;
var fullPath = Path.Combine(directory, library.Name, library.Version, "runtimes", "unix", "lib", "netstandard1.3", $"{library.Name}.dll");
if (File.Exists(fullPath))
{
assemblies.AddRange(new[] { fullPath });
return true;
}
}
return false;
}
}
}
使用系统;
使用System.Collections.Generic;
使用System.IO;
使用Microsoft.DotNet.PlatformAbstractions;
使用Microsoft.Extensions.DependencyModel;
使用Microsoft.Extensions.DependencyModel.Resolution;
名称空间加载器
{
公共类CrudeCompilationAssemblyResolver:ICompilationAssemblyResolver
{
私有只读字符串[]\u NuGetPackageDirectory;
公共反编译程序集解析程序()
{
var basePath=Environment.GetEnvironmentVariable(“HOME”);
var defaultPath=Path.Combine(basePath、.nuget、.packages);
_NuGetPackageDirectory=new[]{defaultPath};
}
public bool TryResolveAssemblyPath(编译库、列表程序集)
{
如果(_NuGetPackageDirectory==null | | | _NuGetPackageDirectory.Length==0 | | |!string.Equals(library.Type,“package”,StringComparison.OrdinalIgnoreCase))
{
返回false;
}
foreach(在_numgetpackagedirectories中的var目录)
{
字符串封装路径;
var fullPath=Path.Combine(目录,library.Name,library.Version,“运行时”,“unix”,“lib”,“netstandard1.3”,“$”{library.Name}.dll”);
if(File.Exists(完整路径))
{
assemblies.AddRange(新[]{fullPath});
返回true;
}
}
返回false;
}
}
}
我的问题是:有没有更好的/官方认可的方法从nuget包加载这个麻烦的程序集?或者我需要让我的原油装载机少很多原油
完整回购在这里:1。为什么要手动加载它?对于项目,NuGet将生成一个包含解析路径的资产文件(输入到deps.json generation)。2.编译程序集解析器并不意味着生成可以加载的程序集,只针对它们进行编译(=>编译器输入,如引用程序集,而不是实际实现)。我宁愿不手动加载它,我有点假设DependencyResolver会为我处理所有这些。我已经看到了
obj/project.assets.json
,我假设它用于生成deps.json
,但我不确定如何使用它。我确实想知道如何使用CompliationAssemblyResolver。我最初使用的是依赖项解析程序中RuntimeLibrary
上的RuntimeAssemblyGroups
属性,但是System.Data.SqlClient
的属性什么都没有,所以我去寻找其他解决方案,偶然发现了第一个链接。1。为什么要手动加载它?对于项目,NuGet将生成一个包含解析路径的资产文件(输入到deps.json generation)。2.编译程序集解析器并不意味着生成可以加载的程序集,只针对它们进行编译(=>编译器输入,如引用程序集,而不是实际实现)。我宁愿不手动加载它,我有点假设DependencyResolver会为我处理所有这些。我已经看到了obj/project.assets.json
,我假设它用于生成deps.json
,但我不确定如何使用它。我确实想知道如何使用CompliationAssemblyResolver。我最初使用的是依赖项解析程序中RuntimeLibrary
上的RuntimeAssemblyGroups
属性,但是System.Data.SqlClient
的属性什么都没有,所以我去寻找其他解决方案,偶然发现了第一个链接。
using System;
using System.Collections.Generic;
using System.IO;
using Microsoft.DotNet.PlatformAbstractions;
using Microsoft.Extensions.DependencyModel;
using Microsoft.Extensions.DependencyModel.Resolution;
namespace Loader
{
public class CrudeCompilationAssemblyResolver : ICompilationAssemblyResolver
{
private readonly string[] _nugetPackageDirectories;
public CrudeCompilationAssemblyResolver()
{
var basePath = Environment.GetEnvironmentVariable("HOME");
var defaultPath = Path.Combine(basePath, ".nuget", "packages");
_nugetPackageDirectories = new [] { defaultPath };
}
public bool TryResolveAssemblyPaths(CompilationLibrary library, List<string> assemblies)
{
if (_nugetPackageDirectories == null || _nugetPackageDirectories.Length == 0 || !string.Equals(library.Type, "package", StringComparison.OrdinalIgnoreCase))
{
return false;
}
foreach (var directory in _nugetPackageDirectories)
{
string packagePath;
var fullPath = Path.Combine(directory, library.Name, library.Version, "runtimes", "unix", "lib", "netstandard1.3", $"{library.Name}.dll");
if (File.Exists(fullPath))
{
assemblies.AddRange(new[] { fullPath });
return true;
}
}
return false;
}
}
}