Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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:\Projects\Dev\TestReferenceInheritance\TestBase\SomeEnvExtandingClass.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?

like image 584
Neowizard Avatar asked Aug 31 '11 09:08

Neowizard


People also ask

What is the difference between project reference and DLL reference?

Well, project references are helpful when you are building and testing in both debug and release mode. If you directly add a DLL then you are locked into whatever that particular DLL was built as. The project reference allows this to be a build time decision. This is correct what you are saying.

Can a DLL reference another DLL?

Any DLL that lays somewhere in file system can be referenced. After compilation this DLL must be either in GAC (Global Assembly Cache) or in same directory with the working application.

How do I fix references in Visual Studio?

To fix a broken project reference by correcting the reference path. In Solution Explorer, right-click your project node, and then select Properties. The Project Designer appears. If you're using Visual Basic, select the References page, and then click the Reference Paths button.


1 Answers

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.

like image 111
David Anderson Avatar answered Sep 18 '22 07:09

David Anderson