为什么使用库A的C#客户机需要为库B(A使用的)提供一个using语句
我有:为什么使用库A的C#客户机需要为库B(A使用的)提供一个using语句,c#,.net,interface,C#,.net,Interface,我有: 主程序类-使用库A 库A-具有与库B中的方法混合的部分类 库B-混合方法和接口 因此,在库B中,当我包含一个实现INode(在库B中定义)的部分节点类时,我突然在我的主类中得到一个错误,它使用库a中的节点。该错误告诉我,在主类中,我必须对库B使用using语句 有什么想法吗 编辑-除代码外 // *** PROGRAM *** class Program { static void Main(string[] args) {
- 主程序类-使用库A
- 库A-具有与库B中的方法混合的部分类
- 库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
}
/***程序***
班级计划
{
静态void Main(字符串[]参数)
{
var context=new Model1Container();
Node myNode;//**没有使用库B我这里有一个错误***
}
}
//**图书馆A
名称空间拓扑
{
公共部分类节点
{
//从EF自动生成
}
公共分部类节点:INode//从库B添加扩展方法
{
公钥
}
}
//**图书馆B
命名空间ToplogyLibrary
{
公共静态类NodeExtns
{
nodeMixin(此INode节点)中的公共静态无效{
//XXXX
}
}
公共接口节点
{
//性质
T键{get;}
//方法
}
}
编辑2-澄清是引用还是使用错误:
因此,“Node myNode;”行出现的错误是:
类型错误1
'Topology.INode'1'是在中定义的
未被引用的程序集。
必须添加对程序集的引用
'拓扑,版本=1.0.0.0,
文化=中立,
PublicKeyToken=null'。U:\My
Dropbox\source\ToplogyLibrary\TopologyDAL\u ConsoleTest\Program.cs 11 13 TopologyDAL\u ConsoleTest
当我让VS为我修复它时,它会添加Library2作为参考。也就是说,在客户机代码之前或之后都没有“使用”。因此,问题是一个参考,而不是使用问题
编辑3-不是特别关于这个问题,但是我现在注意到在程序项目中,我不能看到mixin方法(从库B),除非我有一个对库B的using语句?我可能会就此提出一个单独的问题。如果LibraryA公开属性、从方法返回对象或获取LibraryB中定义的类型的参数,并且您在主程序中声明或使用其中一种类型的变量,您需要using语句。c#中的分部类只是存在于多个文件中的一个类。不能有两个文件在不同的名称空间中定义分部类。由于库a使用库B中的混合方法和接口,如果库a和库B存在于不同的名称空间中,则需要using语句,这正是C的工作方式。编译器需要知道在哪里可以找到库A中使用的库B类型。我的理解是,您只从主程序引用库A,而编译器告诉您添加对库B的引用,因为库A公开的某些类型是在库B中定义的 若要修复此问题,请在主程序项目中添加对库B的引用 这是一个小图表。如果库A公开库B中定义的类型,则Main也必须引用库B。以下情况不起作用:
_____________ _____________ _____________
| Main |references | Library A |references | Library B |
| -|------------|-> -|--------------|-> |
| | | public | | SomeType |
| | | SomeType | | |
| | | | | |
------------- ------------- -------------
只有当库B中定义的类型可通过库a访问时,这才是一个问题。这将发生在以下情况之一:
- 编辑的库A中定义的类型(
)派生自库B中的类型(节点
)INode
- 库A中定义的方法使用库B中的类型作为返回类型或参数李>
- 库A中定义的类型将库B中的类型公开为属性或公共字段
_____________ _____________ _____________
| Main |references | Library A |references | Library B |
| -|------------|-> -|--------------|-> |
| | | public | | SomeType |
| |references | SomeType | | |
| -|------------|------------|--------------|-> |
| | | | | |
------------- ------------- -------------
您所使用的是库A中的
节点
类,这是正确的。但是,节点
类的部分定义是它实现了库B中的INode
接口
节点
类存在的事实要求您包含对库B的引用。正如其他答案正确解释的那样,您的主程序需要对库B的引用,因为库a通过其自己的公共API公开了库B类型。也就是说,节点
公开实现了索引节点
,使得该类型对主程序可见
通常,正确的解决方案只是将库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的公共用法。相反,它使用(前面解释的)代理实例将调用委托给库B中声明的扩展方法。这样,实际上只有库A需要对库B进行引用;主程序可以引用库A而不暴露于库B中的任何类型,因此不需要显式引用
话虽如此,我要重申,事实上,不围绕这个问题工作是有价值的。首先,添加代理可以
public void FromNodeMixin()
{
_nodeProxy.FromNodeMixin();
}