3

我们的应用程序使用了一个相当新的 protobuf-net(版本 2.0.0.668),我正在尝试使用旧版本的 protobuf-net(版本 1.0.0.282)集成到另一个具有客户端库的系统。是否可以在同一个 Windows 服务上使用程序集解析器并排使用库?我知道这些版本之间在序列化程序方面存在重大变化,并且谷歌在版本之间有单独的 protobuf 协议重大变化。

我尝试使用程序集解析器方法,因为我们希望通过退出进程并通过线路为每个客户端调用进行调用来减少调用此客户端库的开销。我想让它并排工作。

即使组装解析器就位(详情如下)。我在需要旧 protobuf 的库上调用了 Assembly.Load,它似乎获得了新版本。即使我没有绑定重定向。我还在项目文件中专门指定了禁用绑定重定向的自动生成。

为什么即使我指定了对项目的特定版本引用以使用版本 1.0.0.282,完全隔离的项目仍默认使用新版本的 protobuf?最终结果是我无法在需要 protobuf.net 版本 1.0.0.282 版本的库上成功序列化 protobuf 消息。

我有不使用 GAC 的限制,也不能创建另一个服务来将对旧版本客户端库的调用包装在另一个服务上,这使得它因进程退出而成为一个非常昂贵的调用。

我的项目结构如下

解决方案 |_WindowsService - 引用 DLL LibraryA 和 DLLLibraryB |_DLL_LibraryA - 引用 protobuf 2.0.0.668 和 DLL_LibraryB |_DLL_LibraryB - 引用 protobuf 1.0.0.282 和 DLL_ThirdpartyClient

DLL_LibraryA 和 DLL_LibraryB 项目是通过引用 protobuf.net 来设置的,以使用特定版本而不是复制本地。

我在 WindowsService 项目上创建了一个构建事件,以便在触发 appdomain resolveassembly 事件时将 bin->ThirdParty->protobuf-net->{version} 文件夹中的 protobuf-net 文件复制到程序集加载器中。

即使我完全隔离程序集并将项目配置设置为禁用绑定重定向的自动生成(禁用自动绑定重定向)。我的程序集加载器只被调用版本 2.0.0.668。

有趣的一件事是,我们的解决方案利用 MEF 进行组合和依赖注入。我想知道它是否有任何影响。同样基于我的解决方案的结构,DLL_LibraryA 依赖于 protobuf-net 2.0.0.668,并且通过 DLL_LibraryB 的依赖关系不直接地依赖于 protobuf-net 1.0.0.282。在这种情况下 clr 做了什么?有没有办法在不退出流程的情况下成功地做到这一点?是因为 CLR 总是决定让我加载最新版本的依赖关系的混合吗?

任何信息将不胜感激。

详情在这里:

  1. 创建版本解析器 - 使用程序集解析器使用并排程序集加载 x64 或 x32 版本的 DLL

        public static Assembly VersionResolver(object sender, ResolveEventArgs args){
         var assemblyName = new AssemblyName(args.Name);
                var name = assemblyName.Name;
                var version = assemblyName.Version.ToString();
                string versionedAssemblyProbingPath = Path.Combine(AppDomain.CurrentDomain.SetupInformation.ApplicationBase,
                                                   string.Format(@"{0}\{1}\{2}", THIRD_PARTY_FOLDER, name, version),
                                                   string.Format("{0}.dll", name));Assembly returnAssembly = null;
            if (File.Exists(versionedAssemblyProbingPath))
            {
                returnAssembly = Assembly.LoadFile(versionedAssemblyProbingPath);
            }
            else
            {
                //Log here and return null
            }
            return returnAssembly;
    }
    
  2. 在 Windows 服务程序中调用解析器 -

    静态程序(){ AppDomain.CurrentDomain.AssemblyResolve += VersionResolver; }

4

0 回答 0