我有两个问题,一个最小的,可重复的例子,有三个项目针对.NET核心3.1。但我也想以.NET Standard2.0为目标。
该示例适用于需要在运行时加载程序集并使用所提供的程序集的应用程序。
加载的程序集引用另一个项目,该项目反过来使用NuGet包。
代码
class Program
{
static void Main(string[] args)
{
var featurePath = System.IO.Path.GetFullPath(@"..\..\..\..\Feature\bin\Debug\netcoreapp3.1\Feature.dll");
var featureAssembly = System.Reflection.Assembly.LoadFile(featurePath);
var featureType = featureAssembly.GetType("SomeFeature");
var featureInstance = System.Activator.CreateInstance(featureType);
featureType.InvokeMember("PrintText",
System.Reflection.BindingFlags.InvokeMethod, null, featureInstance, new object[0]);
}
}SomeFeature.cs:项目特性是一个类库,它具有用于..\Subfeature\Subfeature.csproj的ProjectReference,并包含文件..\Subfeature\Subfeature.csproj
public class SomeFeature
{
public void PrintText()
{
System.Console.WriteLine(new SomeSubfeature().GetText());
}
}Newtonsoft.Json的PackageReference并包含文件Newtonsoft.Jsonpublic class SomeSubfeature
{
public string GetText()
{
return Newtonsoft.Json.JsonConvert.SerializeObject("Some Text");
}
}解决问题
Assembly.LoadFrom只加载请求的程序集。未加载引用项目的程序集和包。这会导致FileNotFoundException,因为找不到子特性。我可以通过(1)将Assembly.LoadFile(featurePath)替换为Assembly.LoadFrom(featurePath)来解决这个问题,这样也可以在同一个目录中加载其他必需的DLL。(2)通过使发布过程中只复制到同一个目录的包DLL在构建过程中也会被复制,从而添加到Feature.csproj <PropertyGroup><CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies></PropertyGroup>中。
的影子副本。
我可以通过(1)将Assembly.LoadFile(featurePath)替换为Assembly.Load(System.IO.File.ReadAllBytes(featurePath))来解决这个问题,以便从加载前读取的字节中加载所需的DLL。(2)如果目录中的DLL文件发生了什么变化,那么让一个文件程序重新加载应用程序。
最终问题
第一个问题的解决方案与第二个问题的解决方案不兼容。Assembly.LoadFrom修复了我的第一个问题。Assembly.Load修复了我的第二个问题。但我还没有为Assembly.LoadFile找到一种同时解决这两个问题的替代方案。
发布于 2020-01-26 15:20:31
将AssemblyResolve事件处理程序添加到AppDomain.CurrentDomain并处理程序集加载,就像读取所有字节一样。
const string location = @"..\..\..\..\Dependency\bin\Debug\netcoreapp3.1\";
static void Main(string[] args)
{
var domain = AppDomain.CurrentDomain;
domain.AssemblyResolve += Domain_AssemblyResolve;
var type = Type.GetType("Dependency.DependentClass,Dependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null");
var obj = Activator.CreateInstance(type);
Console.WriteLine(obj.ToString());
}
private static Assembly Domain_AssemblyResolve(object sender, ResolveEventArgs args)
{
var dll = $"{args.Name.Split(",")[0]}.dll";
var path = Path.Combine(location, dll);
var asm = Assembly.Load(File.ReadAllBytes(path));
return asm;
}附带注意:您需要为类型提供全名,否则会抛出错误。喜欢:"Dependency.DependentClass"
依赖程序集有两个依赖项,一个是Newtonsoft.Json NuGet包,另一个是另一个项目。Bar类驻留在另一个项目中。
public class DependentClass
{
public int MyProperty { get; set; }
public string AnotherProperty { get; set; }
public override string ToString()
{
return JsonConvert.SerializeObject(new Bar());
}
}编辑:在否决投票后,我再次查找了上面的解决方案,尽管它似乎更有可能是一种. net Framework类型的解决方案,而不是.net Core,所以更像. net Core的解决方案是使用AssemblyLoadContext。
定义自定义程序集加载上下文。
public class CustomLoadContext : AssemblyLoadContext
{
private readonly AssemblyDependencyResolver resolver;
public CustomLoadContext(string mainAssemblyToLoadPath) : base(isCollectible: true)
{
resolver = new AssemblyDependencyResolver(mainAssemblyToLoadPath);
}
protected override Assembly Load(AssemblyName name)
{
Console.WriteLine("Resolving : {0}",name.FullName);
var assemblyPath = resolver.ResolveAssemblyToPath(name);
if (assemblyPath != null)
{
return Assembly.Load(File.ReadAllBytes(assemblyPath));
}
return Assembly.Load(name);
}
}加载程序集并让自定义加载器上下文加载它的依赖项。
const string location = @"..\..\..\..\Dependency\bin\Debug\netcoreapp3.1\";
static void Main(string[] args)
{
var fullPath = Path.GetFullPath(location + "Dependency.dll");
var clx = new CustomLoadContext(fullPath); // initialize custom context
var asm = clx.LoadFromStream(new MemoryStream(File.ReadAllBytes(fullPath))); // load your desired assembly
var ins = asm.CreateInstance("Dependency.DependentClass");
Console.WriteLine(ins.ToString());
}https://stackoverflow.com/questions/59865067
复制相似问题