10

I've two projects say P1 and P2.

P1 has a reference of P2.

so I can access P2's methods from P1. But what if I want to access P1's methods from P2 then how can I access them?

I know I can't add P1's reference in P2?

If it is possible? If yes, then how?

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
Naila Akbar
  • 3,033
  • 4
  • 34
  • 76

4 Answers4

20

As others pointed out circular references are the problem. It can't compile P2 before it has compiled P1, but if P1 depends on P2 it can't compile P1 it until P2 has compiled... Got the problem?

Now the solutions:

  • The easy way out: Create a shared library where you put in your shared code of P1 and P2. This shared project can be referenced by both P1 and P2.

  • The better solution: Create an interface which you define in a shared library. Base your 'references' of P2 in P1 on the shared interface, not on the actual implementation. In that way you have a better testable solution and it is easier to replace parts of your code.

Patrick Hofman
  • 153,850
  • 22
  • 249
  • 325
3

Short answer: there is no way of adding P1 as a reference in P2 project as this will create a circular dependency which is not allowed. Consider refactoring your code and designing application in a different way. One way is to introduce another project containing references to both projects.

Alex
  • 937
  • 3
  • 20
  • 44
3

Another way to achieve this is to have P1 reference P2 as project in the solution, but have P2 reference P1 just by its output DLL or EXE.

You lose some cross project / dependency checking, but it does allow you to cross reference.

I had to do this with a long-running WinForms application that was originally written in VB but moved to C# after some years. All new Windows Forms were written in C#, which couldn't be the same project as the VB forms, but some VB forms needed to call the new C# forms and vice verca.

EDIT 1

One drawback with this is that, if P2 references P1 as it's project output DLL/EXE and then, when you clean / rebuild the solution, there's an error, you are in the position where the output DLL/EXE no longer exists and can't be recreated until you resolve the error, but the solution can no longer be built as it has a missing reference. Not a good place to be, so make sure to keep a copy of your output DLL/EXE from time to time so you can get out of this if it ever happens.

Jon Roberts
  • 2,262
  • 2
  • 13
  • 17
  • ohh.. I'll definitely try this approach – Naila Akbar Nov 15 '17 at 06:27
  • By bi-directionally chaining two assemblies together you have made it so that the assemblies will never work without each other (losing code re-usability), but the alternative is to duplicate logic (violating DRY) if you want to share something like logging (and the display of status information) between the application and the dlls. Conceptually, e.g., a dll should not depend on the application using it, but on the other hand, having two separate log files makes it less clear that "doing X in the application caused Y to happen in the DLL". – jrh Nov 30 '17 at 19:39
  • ... in the C/C++ code I've seen, this sort of chaining can't always be avoided, and it's not all that uncommon, it might just depend on why you made a separate DLL in the first place, IIRC Quake 3 did something like this to communicate between its (replaceable) engine components. – jrh Nov 30 '17 at 19:47
  • 4
    @jrh - I agree but in my case we decided to change language about 8 years in. Both projects are logically one single project, but as I can't have c# and vb in the same project, this is a work-around. – Jon Roberts Dec 01 '17 at 16:13
  • @JonRoberts Right, I mostly decided to comment because I can think of cases where you would need to have a circular-ish reference, and I don't think that every assembly necessarily has to act like a re-usable library dll. I think the "shared code" answers are making a lot of assumptions and I can think of valid uses for non-reusable dlls that are mutually dependent on each other; for cases where you really need that, you can refactor until the end of time but the problem is just going to move somewhere else. – jrh Dec 01 '17 at 23:37
1

You can't reference P1 from P2 because it would create a circular dependency. Circular dependency points to bad design. There are ways out of this, for example you can refactor shared code into another project.

Umut Seven
  • 398
  • 2
  • 11
  • 20