如何为DLL而不是EXE选择sgen生成的XmlSerializer DLL?

3
我有一个名叫 ess.exe 的可执行文件。我使用 sgen.exe 为该文件生成一个 XmlSerializer DLL,在运行时它会读入生成的 ess.XmlSerializers.dll 文件,所有操作都很顺利。
我还有一个名叫 EntrianSourceSearch_14.dll 的 DLL,它是通过 Assembly.LoadFrom(DllPathname) 动态加载的。如果我为该 DLL 生成一个 XmlSerializer DLL,它并不会读入这个生成的 DLL;它会回到运行时生成 XML 序列化代码。
如何让我的 DLL 读入相应的生成的 XmlSerializer DLL 呢?
编辑:我不能把 XmlSerializer DLL 放到可执行文件目录中,因为我的 DLL 是 Visual Studio 扩展的一部分 —— 可执行文件是 Visual Studio(devenv.exe),将我的产品的某些部分复制到其目录下可能会被视为反社会行为。 :-)
添加更多上下文的编辑:这是一个 Visual Studio 插件和扩展程序。它适用于从 2005 年到 2017 年的所有版本的 Visual Studio。大部分代码都安装在 Program Files 中,旧版的 Visual Studio 只需作为插件之一从那里加载即可。对于新版的 Visual Studio,不支持插件,只需使用扩展程序来加载位于 Program Files 中的主要组件。这个扩展程序使用 LoadFrom 来加载那些主要组件,其中之一是 EntrianSourceSearch_14.dll

重要的细节应该放在问题中,而不是评论中。尽可能添加更多的上下文信息。 - Hans Passant
运行时 DLL 和动态加载的 DLL 都可能被加载,但它们被加载的顺序可能是我首先要查看的地方。也许这就是为什么总是使用运行时的原因? - Aaron. S
我可能有一个解决方案,但它需要更改调用 Assembly.LoadFrom 的代码 - 你能做到吗?如果可以,请尝试这样做:将 Assembly.LoadFrom 替换为 Assembly.Load(AssemblyName) 并提供 AssemblyNameNameCodeBase 属性。然后在尝试任何 XML 序列化之前使用相同的技术加载您的序列化程序集。您可以尝试仅在序列化程序集上调用 LoadFrom,但是请先阅读此文档 - Lucas Trzesniewski
2
大家要记住,楼主在记录问题时做得很差。这是一个VS扩展程序,它不应该使用LoadFrom,因为所有二进制文件都必须由扩展程序安装程序部署。但是,无论这是插件还是VSIX扩展程序,使用的VS版本以及是否只是用于调试代码都只能瞎猜。 - Hans Passant
@LucasTrzesniewski:谢谢!我尝试了你的建议,但没有成功。从我所读的内容来看,我怀疑任何指定路径名的加载方法最终都会进入“从中加载”上下文,而序列化代码始终使用默认的加载上下文。 - RichieHindle
显示剩余3条评论
1个回答

2
如果您已经构建并部署了一个签名序列化程序集,您可以在加载和缓存序列化器时添加一个CurrentlDomain.AssemblyResolve处理程序,例如:
    private Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        var codeBase = new Uri(Assembly.GetExecutingAssembly().CodeBase).LocalPath;
        var serializerPath = Path.Combine(Path.GetDirectoryName(codeBase), new AssemblyName(args.Name).Name + ".dll");
        if (File.Exists(serializerPath))
            return Assembly.LoadFrom(serializerPath);
        else
            return null;
    }

然而,我找不到一种简单的方法来将序列化程序集的部署包含在单个程序集的VS扩展中。

我找到了一种可能更可取的替代方法。它避免了直接调用Assembly.LoadFrom和上述代码中的一些假设:

  • 将使用Xml Serialization的代码移动到单独的程序集中
  • 对于该程序集:
  • 从扩展包添加一个项目引用到上述程序集
  • 从扩展包添加一个Browse..引用到已构建的序列化程序集

这段代码非常好用(加上 +".dll" 后)- 非常感谢!我有一个问题:为什么你说“如果你已经构建和部署了一个签名的序列化程序集” - 签名程序集有什么区别吗?似乎没有签名也能正常工作... - RichieHindle
已编辑掉那个 bug :). 使用 VS 15 时,当 SGEN 组件未签名时,会出现“需要强名称的程序集”的错误提示。构建过程可能会自动为您签名 SGEN 组件。 - Peter Wishart
我目前是通过手动运行 sgen 来生成汇编代码,因此没有进行明确的签名。不用担心 - 我可以随时进行签名,以防万一。(如果您不介意,那么“需要强名称程序集”错误是如何出现的?是来自 Assembly.LoadFrom() 的异常,还是其他原因?) - RichieHindle
我有一个 AppDomain.FirstChanceException 的处理程序(用于捕获 SGEN 组件的加载失败),该处理程序在 AssemblyResolve 处理程序成功加载 SGEN 组件之后观察到该异常。 - Peter Wishart

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接