Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
197 views
in Technique[技术] by (71.8m points)

c# - Why do I need to reference a dll which I'm not using directly?

I have source code I received from an external developer, this code is divided up into 4 types of projects: Their framework, the environment for my project (lets call it "ENV"), the application base (call it "Base") and the application itself (about 20 dlls I'll collectively call "App").

Now, I've added another layer to this mess, a dll by the name AdvanceFeatures. It lays right under the ENV (on top of the framework). This dll references nothing but the framework, and the ENV references it. Only the ENV makes use of this AdvanceFeatures dll, while Base and App use the only the ENV.

The way I'm working here is most objects in the App are defined in Base and inherit/implement classes/interfaces in ENV. Also a small part of those objects (in App and Base) inherit/implement classes/interfaces from the framework itself (but this is quite rare).

So far all is well, apart from one fact. The compiler demands I'll add a reference to the AdvanceFeatures dll from each one of the dlls in App, and from Base.

I don't make any use of AdvanceFeatures outside of ENV, so why is these references needed?

Edit: I've created a demo project for this problem. This is the project details:

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)
        {
        }
    }
}

I get the error:

Error 1 The type 'AdvanceFeatures.IEnvClass' is defined in an assembly that is not referenced. You must add a reference to assembly 'AdvanceFeatures, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null'. E:ProjectsDevTestReferenceInheritanceTestBaseSomeEnvExtandingClass.cs 3 18 TestBase

Now, I know why the DLL must be made available to the compiled executable, but why should the developer know the inner workings of ENV (more specifically, it's inheritance tree) in order to extend it?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I read all the answers and comments so I came up with this example. Maybe it is a bit easier to understand. :)

Interfaces.dll

public interface DoesntAcceptValidAndAccurateAnswersOrComments {
    bool ImAlwaysRight();
}

Classes.dll - References Interfaces.dll

public class Neowizard : Interfaces.DoesntAcceptValidAndAccurateAnswersOrComments {
    public bool ImAlwaysRight() {
        return true;
    }
}

Program.exe - References Classes.dll

public class StackOverflowDotCom {
    public static void Main() {
        Neowizard someGuy = new Neowizard(); // CS0012
        someGuy.ImAlwaysRight();
    }
}

This has everything to do with the compiler. When it tries to compile Program.exe, it sees an object of type Neowizard. What it also sees is that it implements some interface called DoesntAcceptValidAndAccurateAnswersOrComments, but without a reference to Interfaces.dll it cannot find it, thus it cannot compile because it is an interface that as far as the compiler is concerned, does not exist to Program.exe.

Because Program.exe uses Neowizard, it must also use anything Neowizard derives from, which happens to be the interface. This does not just apply to interfaces, and has zero to do with encapsulation. This a rule of the C# Programming Language that is enforced by the compiler.

If you want to argue the case more, then you should go ask someone on the C# Compiler Team more about it, but please quit dogging on everyone's answer who has tried to help you with your question when their answers are actually quite accurate and well educated.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...