【问题标题】:two different DLL with same namespace具有相同命名空间的两个不同的 DLL
【发布时间】:2011-04-10 00:45:00
【问题描述】:

我有两个 DLL 文件,它们具有相同的命名空间,但它们具有不同的方法和类型。 如何在我的项目中引用这两个 DLL 并使用它们的方法和类型?

顺便说一下,这两个 DLL 有一些方法和类型同名但实现不同,还有一些独特的方法和类型。

【问题讨论】:

  • 我想到的第一个问题是为什么要为同一个命名空间创建 2 个不同的 dll?
  • 他可能只是尝试使用两个碰巧使用相同命名空间的。
  • 我没有创建它。我正在编写一个应该使用 2 个 DLL 的程序,我无法更改它们,因为它们在他们的公司中是稳定的。不幸的是,它们都有相同的文件名和相同的命名空间。
  • 顺便说一句。这两个DLL有一些同名不同实现的函数和类型,以及一些独特的函数和类型。
  • @Searock - 跨多个程序集找到相同的命名空间是很常见的,即使在框架内,尤其是在使用第三方控件时。

标签: c# visual-studio-2010 .net-2.0


【解决方案1】:

您不需要做任何特别的事情 - 只需引用它们并使用类型即可。命名空间可以跨越多个程序集而不会出现问题,因为它们并不是真正不透明的类型。命名空间只是为其包含的所有类型添加公共前缀的一种方式,允许您在不同的命名空间下拥有多个同名的类型。 (框架不会将它们视为具有相同名称,因为它会看到所有内容的“完全限定”名称——它的前面有一个别名和一个命名空间。)

在极少数情况下,您引用了 2 个具有相同类型名称的程序集相同的命名空间(例如同一个 dll 的 2 个不同版本) - 您可以区分哪个程序集用于使用别名给定类型。所有引用的默认别名是 global,但您可以在引用任何程序集时为它指定自己的别名(使用编译器开关 - 或仅使用 Visual Studio 中的属性框) - 并在 extern alias <name> 子句您使用它的代码文件的顶部 - 您可以使用 <name>::MyNamespace.Type 访问来自不同程序集的类型

【讨论】:

【解决方案2】:

您可以使用 /reference (Import Metadata) (C# Compiler Options) 编译器选项的别名功能来解决您的问题,详情请阅读here

【讨论】:

    【解决方案3】:

    如果您有 2 个名称完全相同的类型(请注意,名称包括命名空间)但位于不同的 DLL 中,并且您有兴趣同时使用它们,那么您可以这样做。

    简答

    您在 2 个不同的 DLL 中键入了 Acme.Foo,并且您想使用它们。在引用属性窗口(查看|属性窗口)中给引用一个别名,然后像这样使用它:

    extern alias TheAliasYouGaveTheReference
    
    TheAliasYouGaveTheReference::Acme.Foo f = new 
        TheAliasYouGaveTheReference::Acme.Foo();
    

    默认命名空间是global for any C# program,但请注意上面我们使用的是我们创建的别名而不是global

    最好的方法是首先进入这样的情况,如果两个程序集都是你自己的,那么不要在完全相同的命名空间中创建两个具有完全相同名称的类型.但是有时我们不控制源代码,所以在那个时候,可以使用上面的解决方案。

    长答案

    我从here复制了大部分文章,因此将其记录在这里以防文章不再可用。

    你是如何陷入这样的境地的?

    首先,您可以通过以下方式复制该场景,以便清楚我们在说什么:

    1. 创建一个名为 FooVersion1 的 C# 类库
    2. 将 Class1.cs 中的模板代码替换为:

      using System;
      
      namespace Acme
      {
          public class Foo
          {
              public void Bar()
              {
                  Console.WriteLine("Bar");
              }
          }
      }
      
    3. 在解决方案资源管理器中右键单击解决方案并选择添加 |新项目

    4. 保存当前项目(仅适用于 express)
    5. 在新项目对话框中选择一个类库并将项目名称更改为 FooVersion2 并按 OK
    6. 将 Class1.cs 中的代码替换为以下内容:

      using System;
      
      namespace Acme
      {
          public class Foo
          {
              public void Bar()
              {
                  Console.WriteLine("Bar");
              }
      
              public void Goo()
              {
                  Console.WriteLine("Goo");
              }
          }
      }
      

    类型在Application中的使用

    好的,现在我们有 2 个包含 Acme.Foo 的不同程序集。现在让我们创建一个控制台应用程序并尝试使用每一个。

    1. 在解决方案资源管理器中右键单击解决方案并选择添加 |新项目
    2. 选择一个控制台应用程序并将其命名为消费者
    3. 右击Consumer并选择“设置为启动项目”
    4. 右键单击 Consumer 项目中的引用节点并选择“添加引用”
    5. 单击项目选项卡,并多选 FooVersion1 和 FooVersion2 点击确定
    6. 在 Consumer 项目的 Program 类型的 Main 中添加以下行:

      Acme.Foo f = new Acme.Foo();
      

    通过 Ctrl+Shift+B(或 F6)构建解决方案 请注意,您会收到两个构建错误 [如下所示]:

    修复

    以下是我们可以解决的方法:

    1. 打开解决方案资源管理器并在 Consumer 项目的 References 文件夹中选择 FooVersion1
    2. 按 F4(或选择查看 | 属性窗口)
    3. 将 Aliases 属性更改为 FooVersion1
    4. 构建解决方案
    5. 现在一切都将正确构建,因为 Acme.Foo 明确地引用了 FooVersion2
    6. 在 Consumer 项目的 Program.cs 顶部添加以下指令:

      extern alias FooVersion1;
      
    7. 将 Acme.Foo 的用法改为:

      FooVersion1::Acme.Foo f = new FooVersion1::Acme.Foo();
      f.Bar();
      
    8. 请注意,当您键入“f.”时,完成列表仅包含 Acme.Foo 的 FooVersion1 中的那些方法(特别是它不包括 Goo)

    9. 构建解决方案,一切都会正确构建
    10. 最后在Consumer项目的Program.cs的f.Bar()下添加如下代码:

      Acme.Foo f2 = new Acme.Foo();
      f2.Goo();
      
    11. 请注意 f2 的完成列表包含 Goo。

    12. 使用 Ctrl+Shift+B 再次构建并注意仍然没有构建错误

    【讨论】:

    • 谢谢!我以前从不了解Alias 属性,以前的搜索没有结果。
    • 这样的帖子/答案让你觉得在编程中一切皆有可能。
    • 我如何在 vs 代码中做到这一点?我真的很沮丧,大多数答案总是 VS =(
    猜你喜欢
    • 1970-01-01
    • 2020-07-13
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 2011-05-29
    • 2010-11-12
    • 2014-09-27
    • 2010-10-18
    相关资源
    最近更新 更多