Assembly.LoadFile,Assembly.LoadFrom和Assembly.Load的替代?

问题描述 投票:2回答:1

我在一个最小的,可复制的示例中遇到了两个问题,该示例具有三个针对.NET Core 3.1的项目。

该示例适用于需要在运行时加载程序集并使用提供的程序集的应用程序。

已加载的程序集引用了另一个项目,该项目又使用了NuGet包。

代码

  • project Host是一个控制台应用程序,没有项目引用和包引用。它包含文件Program.cs:
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]);
    }
}
  • project Feature是一个类库,具有..\Subfeature\Subfeature.csproj的ProjectReference并包含文件SomeFeature.cs:
public class SomeFeature
{
    public void PrintText()
    {
        System.Console.WriteLine(new SomeSubfeature().GetText());
    }
}
  • 项目子功能是具有Newtonsoft.Json的PackageReference并包含文件SomeSubfeature.cs的类库:
public 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>中,从而在构建过程中也将其复制。

  • 第二个解决的问题是,应用程序在加载DLL时将其锁定。这样可以防止我在应用程序仍在运行时部署DLL的较新版本。这就使得发布较新的版本变得很麻烦,例如,该应用程序是IIS托管应用程序的一部分。 .NET Core不再支持加载DLL的卷影副本。我可以通过(1)将Assembly.LoadFile(featurePath)替换为Assembly.Load(System.IO.File.ReadAllBytes(featurePath))来解决此问题,以便从加载之前读取的字节中加载所需的DLL。并且(2)如果DLL文件在其目录中发生问题,请使用FileWatcher重新加载应用程序。

  • 最终问题

    第一个问题的解决方案与第二个问题的解决方案不兼容。 Assembly.LoadFrom解决了我的第一个问题。 Assembly.Load解决了我的第二个问题。但是我还没有找到Assembly.LoadFile的替代品同时解决两个问题。

我在一个最小的,可复制的示例中遇到了两个问题,该示例具有三个针对.NET Core 3.1的项目。该示例适用于需要在运行时加载程序集并使用...

c# dll .net-core
1个回答
-1
投票

这是我的解决方法。代替使用Activator创建新实例,请尝试使用AppDomain.CurrentDomainCreateInstanceAndUnwrap方法。并像读取所有字节一样添加AssemblyResolve事件句柄和句柄程序集加载。

        const string location = @"..\..\..\..\Dependency\bin\Debug\netcoreapp3.1\";
        static void Main(string[] args)
        {
            var domain = AppDomain.CurrentDomain;
            domain.AssemblyResolve += Domain_AssemblyResolve;
            object obj = domain.CreateInstanceAndUnwrap(
               "Dependency, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null",
               "Dependency.DependentClass");
            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;
        }
© www.soinside.com 2019 - 2024. All rights reserved.