【问题标题】:How to update an assembly shared between .NET Core and .NET Framework applications如何更新在 .NET Core 和 .NET Framework 应用程序之间共享的程序集
【发布时间】:2018-09-05 19:31:25
【问题描述】:

我有在 .NET Core 2.1 中开发的应用程序 A 和在 .NET Framework 4.7.1 中开发的应用程序 B。他们有一个使用 .NET Standard 2.0 开发的共享库/程序集。这很好用,我可以编译这个库的单个实例并在应用程序 A 和应用程序 B 之间共享它。但这需要每个应用程序 bin 文件夹中的程序集的两个副本。如果应用程序 A 和应用程序 B 部署在同一台机器上,我想在单个位置更新共享程序集的单个实例,并更新应用程序 A 和应用程序 B。鉴于一个使用 .NET Core 而另一个使用 .NET Framework,有没有一种方法可以让应用程序 A 和应用程序 B 在此程序集的同一位置查找?

【问题讨论】:

  • 您可以尝试为该库创建本地 nuget 或私有 nuget 提要。然后你的 App A 和 App B 可以从那里抓取它。虽然这看起来有点矫枉过正,但不完全确定你会怎么做。
  • @penleychan - 在开发应用程序 A 和应用程序 B 的过程中,在此场景中使用 Nuget 来共享此库。但是这个问题针对的是一种部署策略,该策略允许对共享库的任何更新只需要在一个位置删除一个新版本,然后更新应用程序 A 和应用程序 B。
  • 附加到 AppDomain.CurrentDomain.AssemblyResolve 事件,然后调用 Assembly.LoadFile

标签: c# .net .net-core .net-standard


【解决方案1】:

史蒂夫的评论为我指明了正确的方向。这是带有示例的完整答案。我在 .NET Core 和 .NET Framework 中编写了一个简单的控制台应用程序,它调用了一个共享库。该库仅返回要在控制台应用程序中显示的库的版本号。如您所见,这将使测试更容易。这是共享库的全部功能。

using System.Diagnostics;

namespace MyLibrary
{
    /// <summary>
    /// This is a shared library that returns the assemblies version
    /// </summary>
    public class SharedLib
    {
        public string GetProductVersion()
        {
            System.Reflection.Assembly assembly = 
              System.Reflection.Assembly.GetExecutingAssembly();
            FileVersionInfo fvi = FileVersionInfo.GetVersionInfo(assembly.Location);
            string version = fvi.ProductVersion;
            return version;
        }
    }
 }

共享库是针对 .net 标准 2.0 编译的。对于我的测试,我将它作为 NuGet 包发布在本地 NuGet 服务器上。然后,我将 NuGet 包包含在核心和框架应用程序中。这两个应用程序几乎相同。这是代码。

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("Registering Resolving Handler...");
        AppDomain.CurrentDomain.AssemblyResolve += MyHandler;
        Console.WriteLine("Creating shared library...");
        SharedLibWrapper sharedLib = new SharedLibWrapper();
        Console.WriteLine("The version is {0}", sharedLib.Version);
        Console.WriteLine("Press Enter key to continue...");
        Console.ReadLine();

    }

    static string GetSharedAssemblyPath()
    {
        string relativePath = @"..\..\..\SharedAssemblies\";
        return Path.GetFullPath(relativePath);
    }

    static Assembly MyHandler(object source, ResolveEventArgs e)
    {
        Console.WriteLine("Resolving {0}", e.Name);
        if (e.Name.Contains("MyLibrary"))
        {
            string path = GetSharedAssemblyPath() + @"MyLibrary.dll";
            Console.WriteLine("Resolving to path {0}", path);
            return Assembly.LoadFile(path);
        }
        return null;
    }
}

此代码添加了一个AssemblyResolve 处理程序,以便在应用程序找不到程序集的情况下,处理程序将尝试解析它。在这种情况下,我让两个应用程序都在位于解决方案根目录的 SharedAssemblies 文件夹中查找。

您会注意到我将共享库放在类包装器中。这是我能让解决方案发挥作用的唯一方法。如果我直接在 Main 方法中引用了共享库,应用程序会在注册事件处理程序之前尝试加载程序集。

现在,当我编译应用程序并运行它们时,我会得到以下输出。

正在注册解析处理程序...

正在创建共享库...

版本是1.0.10765

按 Enter 键继续...

现在让我们将新版本的共享库放在 SharedAssemblies 文件夹中,并删除与应用程序一起发布的库。现在这是输出。

正在创建共享库...

正在解析 MyLibrary,版本=1.0.10765.0,文化=中性, PublicKeyToken=null

解析到路径 C:...\SharedLibrary\SharedAssemblies\MyLibrary.dll

版本是1.0.10930

按 Enter 键继续...

Core 和 Framework 应用程序的结果相同。请注意,我们可以将更新版本的程序集放在 SharedAssemblies 文件夹中,它仍然可以正确加载。这是我正在寻找以允许更新共享库的结果。现在我可以将它放在一个位置并更新两个应用程序。但是,如果我出于某种原因只想更新一个应用程序,我仍然可以通过将所需版本放入应用程序的 bin 文件夹中。这是可行的,因为程序集解析器将首先在本地 bin 中查找,如果在共享位置找不到,则仅从共享位置中提取。

您可以在this GitHub project 上获取所有的源代码来玩这个。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-01-22
    • 1970-01-01
    • 1970-01-01
    • 2017-08-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多