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

时间:2010-05-20 21:21:25

标签: c# .net interface

我有:

  • 主程序类 - 使用库A
  • 图书馆A - 有部分类,混合了图书馆B的方法
  • 图书馆B - 混合方法&接口

所以在库B中,当我包含一个实现INode的部分Node类(在库B中定义)时,我突然在我的主类中出现错误,它使用来自库A的Node。错误告诉我在Main Class中我有对库B有一个使用声明。

有什么想法吗?

编辑 - 代码

除外
    // *** PROGRAM ***
    class Program
    {
        static void Main(string[] args)
        {
            var context = new Model1Container();
            Node myNode;  // ** WITHOUT A using for Library B I have an error here ***
         }
     }


// ** LIBRARY A
namespace TopologyDAL
{
    public partial class Node
    {
        // Auto generated from EF
    }

    public partial class Node : INode<int>   // to add extension methods from Library B
    {
        public int Key
    }
}

// ** LIBRARY B
namespace ToplogyLibrary
{
    public static class NodeExtns
    {
        public static void FromNodeMixin<T>(this INode<T> node) {
           // XXXX
        }
    }
    public interface INode<T> 
    {
        // Properties
        T Key { get; }

        // Methods
    }

}

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

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

  

错误1类型   'Topology.INode`1'在中定义   未引用的程序集。   您必须添加对程序集的引用   '拓扑,版本= 1.0.0.0,   文化=中性,   公钥=空”。 U:\我的   Dropbox \ source \ ToplogyLibrary \ TopologyDAL_ConsoleTest \ Program.cs 11 13 TopologyDAL_ConsoleTest

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

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

6 个答案:

答案 0 :(得分:5)

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

答案 1 :(得分:5)

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

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

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

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

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

  • 已编辑库A中定义的类型(Node)派生自库B中的类型(INode<int>)。
  • 库A中定义的方法使用库B中的类型作为返回类型或参数。
  • 库A中定义的类型将库B中的类型公开为属性或公共字段。

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

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

答案 2 :(得分:1)

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

答案 3 :(得分:0)

您正在使用的是图书馆A中的Node课程,这是真的。但是,Node类的部分定义是它实现了库B中的INode<int>接口。

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

答案 4 :(得分:0)

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

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

但是如果由于某种原因添加引用是有问题的,有一个替代方案,假设您至少可以更改库A.这是封装使用库B中的类型,以便它们使用库A对代码可见。通常,这种封装将涉及某种代理或包装,以隐藏第三个库的使用和(在某些情况下)将第三个库的功能暴露给引用第二个库的程序集。

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

namespace TopologyDAL
{
    public partial class Node
    {
        // Auto generated from EF
    }

    public partial class Node
    {
        public int Key { ... }

        private class NodeProxy : INode<int>
        {
            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中访问扩展方法而不引用该库,该怎么办?

好吧,我的第一个答案是&#34;请继续参考大会!&#34; :)但是为了争论,让我们说你出于某种原因无法做到这一点,或者至少这样做非常不方便。然后,您可以扩展代理方法,以将代理方法添加到库A类型,然后再将类型委托给库B中的实现。

扩展上面的例子,可以在Node类声明中添加另一种方法:

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

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


现在说了这些,我将重申 实际上在而不是处理该问题的价值。首先,添加代理可能非常耗时。它只适用于一两种类型,可能有一些方法。但是,如果你试图隐藏每一个间接使用DLL的方法,那么它将真正快速实现,否则你将使用大量的功能。

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

答案 5 :(得分:-1)

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