0

I have three C# library projects targeting .NET Framework 4:

  • Project A: Contains classA.
  • Project B: References Project A.
  • Project C: References Project B.

I want to use classA in Project C. However, it only works if I add a direct reference from Project C to Project A, which I want to avoid.

Is there a way to use classA in Project C without adding a direct reference to Project A, maintaining the current reference structure (B referencing A, and C referencing B)?

Here is a screenshot for what I am trying to do:

enter image description here

Thank you for your help!

7
  • You can't use the Class if you do not reference the library it is contained in. If you explain why you can't do the direct reference maybe I can help more. May 20 at 13:55
  • Please don't use unrelated tags and post the code as text. Images can't be copied, compiled or tested. Post enough code to actually reproduce the problem. How is ClassA defined? In what namespace? You'll still get an error even after adding a reference unless you add using netCoreA or use netCore.ClassA May 20 at 13:57
  • @0x436f72647265 I want to use an intermediate class to override the definition of classes beacause the project A is gonna be delivered as DLL, and the project B is a project where I can do my modification on a service for example and override its methods etc.. and it should be impacting the whole logic of the application, and avoid changing wherever I wanna call it.
    – Hasagiii
    May 20 at 14:03
  • 1
    AFAIK this works. Sometimes the helper methods of VS don't work as intended. Have you tried to fully qualify the name of ClassA manually? If yes, what was the error message?
    – Oliver
    May 20 at 14:03
  • @Oliver it gives me the following error : the type of namespace 'netCoreA' could not be found (are you missing a using directive or an assembly reference ?), I gave example with .net core projects but actualy I have my projects in .net framework 4.
    – Hasagiii
    May 20 at 14:09

2 Answers 2

0

In order to able to interact with a class you need to know it's API, i.e., its public members. To achieve this with dynamically loaded assemblies you can declare an interface that its exposed classes implement. You will need an additional assembly (a class library) containing the interface(s).

Project "Contracts" (interfaces)
^
|
+-- Project "A"
^       ^
|       |
+-- Project "B"
^       ^
|       |
+-- Project "C"

The projects A, B, C must also reference "Contracts"

Example:

// Project "Contracts"

public interface IA
{
    void DoA();
}

public interface IB
{
    void DoB(IA a);
}
// Project "A"
public class A : IA
{
    public void DoA()
    {
        Console.WriteLine("A");
    }
}
// Project "B"
public class B : IB
{
    public void DoB(IA a);
    {
        Console.Write("B calling ");
        a.DoA();
    }
}

The main project can now load the assemblies dynamically, create objects and cast them to the known interfaces.

See Create a .NET Core application with plugins where it is explained how you can load an assembly at runtime (this got a bit complicated in .NET Core and was easier in .NET Framework). I am not going to repeat all the details here. Once you have loaded the assembly, you can search for types implementing a given interface with

foreach (Type type in assembly.GetTypes()) {
    if (typeof(IA).IsAssignableFrom(type))
    {
        if (Activator.CreateInstance(type) is IA a)
        {
            a.DoA();
        }
    }
}
4
  • This is the answer, though I would do it using Dependency Injection. Register ClassA as an implementation of InterfaceA, then resolve interfaceA in ProjectC. May 20 at 14:23
  • You can certainly configure whatever IoC container you're using to provide the instance using this method when requesting the interface.
    – Alejandro
    May 20 at 14:30
  • This answer is fundamentally what plugin systems do. The project with the interface is the host application and the project with the class is the plugin. The plugin knows about the host, but the host don't knows the plugin.
    – Alejandro
    May 20 at 14:31
  • Yes, but you don't know the type name of the class at compile time, so you will have to register it either by using a System.Type or by using a factory method calling one of the (IA)Activator.CreateInstance() overloads. May 20 at 14:32
0

I don't know what your goal is but maybe this example can help you:

ClassA in netCoreA project:

public class ClassA
{
    public void PrintA()
    {

    }
}

Factory in netCoreB project referencing netCoreA:

public class Factory : IFactory
{
    public ClassA CreateClassA()
    {
        return new ClassA();
    }
}

In netCoreC project referencing netCoreB:

public class ClassC
{
    public ClassC(IFactory factory)
    {
        var classA = factory.CreateClassA();
        classA.PrintA();
    }
    
}
New contributor
Anonymous is a new contributor to this site. Take care in asking for clarification, commenting, and answering. Check out our Code of Conduct.
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.