【问题标题】:Using a type, without knowing about the dll使用类型,不知道 dll
【发布时间】:2012-02-21 14:59:51
【问题描述】:

是否可以使用在一个巨大的外部 dll 中定义的接口类型,而不引用该 dll? 换句话说,会有一个核心或全局 dll 引用外部 dll,并且所有项目都引用这个全局 dll,因此外部 dll 对其他项目是隐藏的。

我想在我的代码中使用该类型,但只知道全局 AllInterfaces 项目。 那行得通吗?如果是这样,这种情况需要做什么?

【问题讨论】:

  • 看看依赖注入模式,这可能会给你一些想法。这里的简短展望:c-sharpcorner.com/UploadFile/ff2f08/…
  • 我想知道如果您需要静态使用界面,DI将如何提供帮助
  • 如果你只需要那一种,为什么不把它引入你的项目呢?
  • 也许我很密集。将它引入我的项目意味着什么?该场景是外部 dll 处理实现其接口的对象。我想对我的客户隐藏外部 dll,并且仍然在静态区域中。

标签: c# dll dependencies using


【解决方案1】:

它不能静态完成,但您可以使用反射来完成。

【讨论】:

    【解决方案2】:

    如果您想在代码中使用该接口类型,则该接口应该对您的代码可见。你的代码不会编译。

    您可以在全局 dll 中为原始接口编写适配器接口,并在任何地方使用它。

    【讨论】:

    • 这行得通吗?如果我理解正确,您建议将该接口复制到我的命名空间中。但是外部dll类没有实现其他接口吗?
    【解决方案3】:

    在 C# 4 中,您可以使用 dynamic 关键字。

    但是,我看不出事先不知道接口对你有什么帮助——你怎么知道要调用哪些方法?

    【讨论】:

    • 我认为你的意思是 .net4 没有任何名称为 c#4。
    • 我的意思是 C# 4(大多数时候都带有 .NET 4)。动态是一种语言特性。不过,我不知道您是否可以将 dymanic 与 CLR 的前 4 个版本一起使用 - 如果您感兴趣,值得一试。
    • @Saeed 是的,你可以叫它C# 4.0
    • 事实证明你不能,如果你尝试在 CLR 2.0 版中使用动态,编译器会抱怨它缺少某些类型。有道理。
    • @zmbq 动态关键字不是最好的方法,我认为反射在这种情况下会有所帮助,因为它与CLR有关并且更灵活。
    【解决方案4】:

    你试图欺骗输入身份。 CLR 通过以下属性识别类型:

    • 程序集显示名称
    • [AssemblyVersion]
    • [组装文化]
    • 程序集的 PublicKeyToken 值
    • 程序集的处理器架构(隐式)
    • 类型的命名空间名称
    • 类型的名称。

    伪造类型命名空间名称和名称并不难,难的是伪造程序集属性。如果程序集是强命名的(非 null PublicKeyToken)或者如果它存储在 GAC 中,那么您将无法加载替代程序。伪造文化和架构并不难,您必须获得正确的显示名称和版本。

    当然,您必须完全正确地获得接口声明。像这样故意调用 DLL Hell 是一个非常糟糕的主意。至少没有,因为您现在永远无法加载真正的程序集。

    【讨论】:

      【解决方案5】:

      是否可以使用在巨大的外部 dll 中定义的接口类型,而无需在编译时引用该 dll?

      不是真的,不。编译器有合理的期望,即它需要的类型是可用的。

      是否可以使用在巨大的外部 dll 中定义的接口类型,而无需在运行时引用该 dll?

      是的。我们在 C# 4 中添加了该功能。该功能的“正确”名称类似于“Type Embedding with Type Equivalence”,但每个人都称其为“No PIA”。

      该功能的动机是 Visual Studio Tools For Office 开发人员最明显面临的动机。 VSTO 开发人员编写 C# 代码来自定义(例如,使用一些托管代码的 Excel 电子表格)。它们通过托管接口与 Excel 进行通信,当然 Excel 实际上公开了一组 COM 接口。为了弥补这一差距,Office 团队提供了一个主互操作程序集或 PIA。 PIA 是一个庞大的外部库,它只包含描述托管接口如何对应于 COM 对象的非托管接口的元数据。

      问题在于,当您的客户购买 Office 时,Office 团队默认不会安装 PIA!因此,必须随您的定制一起发布 PIA。而且PIA太大了,往往是自定义大小的好几倍,让你下载的时间更长。等等;无论如何,这都不是一个理想的情况。

      No-PIA 功能允许编译器仅将您实际使用的 PIA 部分链接到您的库中,这样您就不必随它一起发布 PIA。

      现在,您可能会问“如果我有两个相互通信的自定义项,并且两者都使用我未发布的 PIA 中的 IFoo 接口怎么办?”运行时通过 它们来自的程序集,因此这两个 IFoo 接口将被视为不同的类型,因此不兼容。

      “无 PIA”功能也考虑到了这一点。它使用您在 COM 中用来解决此问题的相同技巧:程序集指示运行时将具有相同 GUID 的所有接口统一为相同的逻辑类型,即使它们来自不同的程序集。因此,这就解释了这样的要求,即您使用“无 PIA”的每个接口都必须被标记为好像它是带有 GUID 的 COM 互操作接口。

      在命令行上,使用 /L 而不是 /R 将程序集引用为“无 PIA”程序集。

      在“no PIA”上进行网络搜索,您会找到有关此功能的更多信息。

      【讨论】:

      • 类型嵌入仅适用于具有 [ComImport] 属性的类型。 “巨大的外部 DLL”是模棱两可的,但几率似乎很低。如果它实际上是一个 pia,那么与 dynamic 的后期绑定是一个未提及的替代方案。
      猜你喜欢
      • 1970-01-01
      • 2011-12-27
      • 2016-05-18
      • 2019-04-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-08-17
      相关资源
      最近更新 更多