我有从外部开发人员那里收到的源代码,这段代码分为4种类型的项目:他们的框架,我项目的环境(让我们称之为“ENV”),应用程序库(称之为“Base”) “)和应用程序本身(大约20个dll我将统称为”App“)。
现在,我已经在这个混乱中添加了另一个图层,一个名为AdvanceFeatures的dll。它位于ENV(框架顶部)的正下方。 这个dll只引用框架,ENV引用它。 只有ENV使用这个AdvanceFeatures dll,而Base和App只使用ENV。
我在这里工作的方式是App中的大多数对象都是在Base中定义的,并在ENV中继承/实现类/接口。这些对象中的一小部分(在App和Base中)从框架本身继承/实现类/接口(但这种情况非常罕见)。
到目前为止,一切都很顺利,除了一个事实。编译器要求我将从App中的每个dll和Base中添加对AdvanceFeatures dll的引用。
我没有在ENV之外使用AdvanceFeatures,那么为什么需要这些引用呢?
编辑:我已经为这个问题创建了一个演示项目。这是项目细节:
Assembly: AdvanceFeatures
References: Nothing (Reference project-folder is empty)
Classes: Decorator, IEnvClass, IDecorator
IDecorator contents:
namespace AdvanceFeatures
{
public interface IDecorator
{
IEnvClass Decorated { get; }
void Decorate();
}
}
IEnvClass contents:
namespace AdvanceFeatures
{
public interface IEnvClass
{
string Name { get; set; }
}
}
Decorator contents:
namespace AdvanceFeatures
{
public class Decorator : IDecorator
{
public Decorator(IEnvClass decorated)
{
Decorated = decorated;
}
#region Implementation of IDecorator
public IEnvClass Decorated { get; set; }
public void Decorate()
{
Decorated.Name = "NewName";
}
#endregion
}
}
Assembly: ENV
References: AdvanceFeatures (Compiled DLL)
Contents of only class SomeEnvClass:
namespace ENV
{
public class SomeEnvClass : AdvanceFeatures.IEnvClass
{
public string Name { get; set; }
private readonly AdvanceFeatures.IDecorator _decorator;
public SomeEnvClass(string name)
{
Name = name;
_decorator = new AdvanceFeatures.Decorator(this);
_decorator.Decorate();
}
public string Foo()
{
return Name;
}
}
}
Assembly: TestBase
References: ENV (compiled DLL)
Contents of only class SomeEnvExtendingClass:
namespace TestBase
{
public class SomeEnvExtandingClass : ENV.SomeEnvClass
{
public SomeEnvExtandingClass(string name) : base(name)
{
}
}
}
我收到错误:
错误1“AdvanceFeatures.IEnvClass”类型在未引用的程序集中定义。您必须添加对程序集'AdvanceFeatures,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null'的引用。 E:\ Projects \ Dev \ TestReferenceInheritance \ TestBase \ SomeEnvExtandingClass.cs 3 18 TestBase
现在,我知道为什么DLL必须可用于编译的可执行文件,但为什么开发人员应该知道ENV的内部工作方式(更具体地说,它是继承树)以扩展它?
答案 0 :(得分:10)
我阅读了所有的答案和评论,所以我想出了这个例子。也许它更容易理解。 :)
Interfaces.dll
public interface DoesntAcceptValidAndAccurateAnswersOrComments {
bool ImAlwaysRight();
}
Classes.dll - 引用Interfaces.dll
public class Neowizard : Interfaces.DoesntAcceptValidAndAccurateAnswersOrComments {
public bool ImAlwaysRight() {
return true;
}
}
Program.exe - 引用Classes.dll
public class StackOverflowDotCom {
public static void Main() {
Neowizard someGuy = new Neowizard(); // CS0012
someGuy.ImAlwaysRight();
}
}
这与编译器有关。当它尝试编译Program.exe时,它会看到一个Neowizard类型的对象。它还看到它实现了一些名为DoesntAcceptValidAndAccurateAnswersOrComments的接口,但是没有对Interfaces.dll的引用它找不到它,因此它无法编译,因为它是一个接口,就编译器而言,不存在于Program中。可执行程序。
因为Program.exe使用Neowizard,它还必须使用Neowizard派生的任何东西,它恰好是接口。这不仅适用于接口,而且与封装无关。这是C#编程语言的一个规则,由编译器强制执行。
如果你想更多地论证这个案子,那么你应该去问一下C#编译器团队的更多人,但是当他们的答案实际上非常准确时,请放弃试图帮助你解决问题的每个人的答案并且受过良好教育。
答案 1 :(得分:4)
如果你在一个集会中
public class Bar{
...
}
而另一个有
public class Foo{
public Bar MyBar{get;set;}
}
和第三个
public class FooBar{
public Foo {get;set;}
}
然后你可以写:
Bar myBar = new FooBar().Foo.MyBar;
如果你还没有告诉编译器关于bar的定义怎么能编译最后一行代码?
或更直接地回答您的问题。当使用引用另一个程序集的程序集时,您的代码可能直接使用来自其他程序集的东西。如果在其他程序集中声明了返回类型,或者在方法的实现中使用了另一个程序集中定义的类型的对象,或者直接引用的程序集中的私有字段时间接声明了返回类型。编译器需要知道这些类型才能完成它的工作。它依赖于你告诉它在哪里可以找到这些类型的信息。即添加引用
修改强>
为了澄清一点,没有规则要求您引用与您正在使用的dll相同的dll。你必须引用一个说它是相同的dll。这就是为什么你可以签署一个DLL。那么你是gauranteed它总是相同的实现(或至少由一些人访问密钥)
使用不同程序集的可能性但是强制要求在dll /程序中使用中间的dll。您需要明确声明要使用的给定程序集的哪个实现。
答案 2 :(得分:1)
基本上有两种可能性: