为什么我需要引用一个我没有直接使用的dll?

时间:2011-08-31 09:08:22

标签: c# inheritance reference

我有从外部开发人员那里收到的源代码,这段代码分为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的内部工作方式(更具体地说,它是继承树)以扩展它?

3 个答案:

答案 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)

基本上有两种可能性:

  1. 您可以使用AdvanceFeatures库的一部分而不会意识到它,例如在某些时候获取对从AdvanceFeatures中的类继承的类的引用。这个类可能很小,你可能在AdvanceFeatures中有一个enum,它可以通过ENV中的方法返回。
  2. 你没有做过这样的事情,只是图书馆仍然需要在那里。除非你在ENV中嵌入了AdvanceFeature dll,否则你实际上无法在没有AdvanceFeature的情况下使用ENV。通常,这只意味着它需要与可执行文件位于同一文件夹中。可能值得检查是否已将库设置为在其属性中复制本地等,或者对其属性的引用。