0

I'm using visual studio to create a windows app and I have the following problem.

I get a circular dependency error because I have this setup:

project1.classA.cs

project2.classB.cs
project2.classC.cs

Now, classB has a member of classA, so I have added a reference to project1. Now I would like class A to make use of static functions in classC. However I cannot add a reference to project2 because of the circular dependency. Is there any way to solve this that doesn't involve me creating a new project?

Frank
  • 2,446
  • 7
  • 33
  • 67
  • Add your class's code for each class, please? – Nick Bull Aug 09 '16 at 09:46
  • 1
    try searching for **c# circular dependency interface** – Mong Zhu Aug 09 '16 at 09:50
  • 1
    You can have circular references between assemblies but you can't rely on VS to help you and you need to customize your build, as well as having to make serious changes to the classes. Make sure you *really* need this before you embark down this path. Are you using a weird Edition of VS where you have to pay them for each project you create? – Damien_The_Unbeliever Aug 09 '16 at 10:03
  • 1
    [Here's](http://stackoverflow.com/a/37829855/15498) an example of how to create two mutually referencing assemblies. – Damien_The_Unbeliever Aug 09 '16 at 10:16
  • 1
    While not really an answer, if you find yourself in such a position then it means you've mixed up the purposes of the various projects. In other words, such a situation should be avoided. Simplest solution would be to move common elements to yet a separate, more global project, or rethink your code structure. – MBender Aug 09 '16 at 10:22
  • Even simpler solution - since at runtime you're almost always going to force both assemblies to be loaded in order for both to be functional - *merge* the projects. That's a solution that doesn't involve creating a new project – Damien_The_Unbeliever Aug 09 '16 at 11:58

2 Answers2

1

I think you are better off extracting the common methods and interfaces and putting them in a separate class library.

However, it is possible to do it without writing a new class library by inventing an interface for class C and putting it in project 1:

public interface IClassC
{
    void Method1();
    void Method2();
}

Then inside project 1, you can use dependency injection to pass it to the ClassA constructor:

public class ClassA
{
    readonly IClassC _methodsFromClassC;

    public ClassA(IClassC methodsFromClassC)
    {
        _methodsFromClassC = methodsFromClassC;
    }

    public void SomeMethod()
    {
        _methodsFromClassC.Method1();
        _methodsFromClassC.Method2();
    }
}

Then in project 2 you would need to implement that interface using the static ClassC:

public static class ClassC
{
    public static void Method1()
    {
        Console.WriteLine("ClassC.Method1()");
    }

    public static void Method2()
    {
        Console.WriteLine("ClassC.Method2()");
    }
}

public class ClassCImpl : IClassC
{
    public void Method1()
    {
        ClassC.Method1();
    }

    public void Method2()
    {
        ClassC.Method2();
    }
}

Then when you create an instance of ClassA you would have to pass an instance of ClassCImpl:

var classA = new ClassA(new ClassCImpl());

However, to reiterate: You should really be creating a separate class library to hold the shared interfaces and classes.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • 1
    The interface option doesn't seem viable here since they say they're calling `static` functions in `ClassC`. – Damien_The_Unbeliever Aug 09 '16 at 10:10
  • 1
    @Damien_The_Unbeliever Look at the code I posted. It uses class `ClassCImpl` to wrap the calls to static methods in the static `ClassC`, and passes an instance of `ClassCImpl` to the the `ClassA` constructor. – Matthew Watson Aug 09 '16 at 10:16
1

This is not a great situation to be in, but the fact that you don't want to have to create a new project leads me to believe that you have considered all sensible options.

I think the only option left to you is to add the file project2.classC.cs itself in to project1, but be sure to tick the 'include as link' option in the 'select' dialog so that you don't make a copy. It's not nice, but it should work.

Right-click on the project, select Add->Existing Item, select the file, and then click the drop-down on the right of the Add button and select Add as Link.

LordWilmore
  • 2,829
  • 2
  • 25
  • 30