为什么我使用库A的C#客户端需要有一个库B的使用语句(A使用)

我有:

  • 主程序类 – 使用库A.
  • 图书馆A – 具有部分类,它们混合了图书馆B的方法
  • 库B – 混合方法和接口

所以在库B中,当我包含一个实现INode的部分Node类(在库B中定义)时,我突然在我的主类中出现错误,它使用来自库A的Node。错误告诉我在主类中我必须有一个使用语句到库B.

有任何想法吗?

编辑 – 除了代码

// *** PROGRAM *** class Program { static void Main(string[] args) { var context = new Model1Container(); Node myNode; // ** WITHOUT A using for Library BI have an error here *** } } // ** LIBRARY A namespace TopologyDAL { public partial class Node { // Auto generated from EF } public partial class Node : INode // to add extension methods from Library B { public int Key } } // ** LIBRARY B namespace ToplogyLibrary { public static class NodeExtns { public static void FromNodeMixin(this INode node) { // XXXX } } public interface INode { // Properties T Key { get; } // Methods } 

}

编辑2 – 澄清是引用还是使用错误:

所以针对“Node myNode”出现的错误; 线是:

错误1类型’Topology.INode`1’在未引用的程序集中定义。 您必须添加对程序集“Topology,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”的引用。 U:\ My Dropbox \ source \ ToplogyLibrary \ TopologyDAL_ConsoleTest \ Program.cs 11 13 TopologyDAL_ConsoleTest

当我让VS为我修复它时,它添加了Library2作为参考。 也就是说,在客户端代码之前或之后没有“使用”。 所以问题是参考不使用问题。

编辑3 – 不是特别关于这个问题,但我现在注意到在程序项目中,我看不到mixin方法(来自库B),除非我有一个使用语句到库B? 我可能会创建一个单独的问题。

我对正在发生的事情的理解是,您只从主程序中引用库A,编译器会告诉您添加对库B的引用,因为库A中公开的某些类型是在库B中定义的。

要解决此问题,请将库B的引用添加到主程序项目中。

这是一个小图。 如果库A公开了库B中定义的类型,那么Main也必须引用库B. 以下情况不起作用:

 _____________ _____________ _____________ | Main |references | Library A |references | Library B | | -|------------|-> -|--------------|-> | | | | public | | SomeType | | | | SomeType | | | | | | | | | ------------- ------------- ------------- 

当库B中定义的类型可通过库A访问时,这只是一个问题。这将是以下情况之一:

  • 在库A( Node )中定义的EDITED类型源自库B中的类型( INode )。
  • 库A中定义的方法使用库B中的类型作为返回类型或参数。
  • 库A中定义的类型将库B中的类型公开为属性或公共字段。

您需要从Assembly1添加对Assembly3的引用以使其进行编译。

 _____________ _____________ _____________ | Main |references | Library A |references | Library B | | -|------------|-> -|--------------|-> | | | | public | | SomeType | | |references | SomeType | | | | -|------------|------------|--------------|-> | | | | | | | ------------- ------------- ------------- 

如果LibraryA公开属性,从方法返回对象,或者获取LibraryB中定义的类型的参数,并且在其中一种类型的主程序中声明或使用变量,则需要using语句。

由于库A在库B中使用混合方法和接口,如果库A和库B存在于不同的命名空间中,则需要使用using语句,这就是C#的工作原理。 编译器需要知道在哪里可以找到库A中使用的库B类型。

您正在使用的只是库A中的Node类,这是真的。 但是, Node类定义的一部分是它实现了库B中的INode接口。

Node类存在的事实要求您包含对库B的引用。

正如其他答案已正确解释,您的主程序需要引用库B,因为库A已通过其自己的公共API公开了库B类型。 即Node公开实现INode ,导致该类型对主程序可见。

通常,正确的解决方案只是将库B的引用添加到主程序中。 毕竟,主程序在运行时肯定需要库B,即使它本身不直接访问该库中声明的任何类型。

但是,如果出于某种原因添加引用是有问题的,可以选择库A来封装使用库中的类型,以便使用库对代码可见。答:通常,这种封装将涉及某种代理或包装,以隐藏第三个库的使用和(在某些情况下)将第三个库的特征暴露给引用第二个库的程序集。

例如,您可以将库A更改为如下所示:

 namespace TopologyDAL { public partial class Node { // Auto generated from EF } public partial class Node { public int Key { ... } private class NodeProxy : INode { private readonly Node _node; public NodeProxy(Node node) { _node = node; } public int Key { get { return _node.Key; } } } private readonly NodeProxy _nodeProxy; public Node() { _nodeProxy = new NodeProxy(this); } } } 

然后,只要您想使用库B中的扩展方法,就可以使用_nodeProxy成员而不是this

当然,上面假设主程序实际上没有直接使用库B中的任何内容,并且库B中所有类型的用法都只在库A中找到,甚至没有在库A中以返回值,属性类型公开等等但是如果不是这样呢? 例如,如果您希望主程序能够从库B中访问扩展方法而不引用该库,该怎么办?

好吧,我的第一个答案就是“继续前进并参考大会!” :)但是为了争论,让我们说你出于某些原因不能这样做,或者至少这样做非常不方便。 然后,您可以扩展代理方法,以将代理方法添加到Library A类型,然后将其委托给库B中的实现。

例如,扩展上面的内容,可以向Node类声明添加另一种方法:

 public void FromNodeMixin() { _nodeProxy.FromNodeMixin(); } 

请注意,该方法本身不添加库B的公共用法。相反,它使用(先前解释的)代理实例将调用委托给库B中声明的扩展方法。这样,只有库A实际上需要具有引用到图书馆B; 主程序可以引用库A而不暴露于库B中的任何类型,因此不需要显式引用。

现在所说的一切,我将重申,事实上并没有解决这个问题的价值。 首先,添加代理可能非常耗时。 它只适用于一两种类型,可能只有几种方法。 但是如果你试图隐藏DLL的每一个间接使用,否则它将真正快速实现,否则你将使用大量的function。

同样如我之前提到的,当然不必添加对库B的引用并不意味着库B不需要存在以供程序运行。 您仍然需要在那里拥有库,以便在库A调用它时,可以使用它。 拥有主程序参考库B是我所知道的最简单的方法之一,以确保将库B复制到构建输出目录以确保DLL存在。

c#中的部分类只是存在于多个文件中的类。 您不能有2个文件在不同的命名空间中定义部分类。