9

I have two assemblies A & B.

A has existing reference to B and it must be kept that way. Right now I made some changes to B that need to refer to A. So circular reference occurs.

Bit of details:

A has a few property grids that the dialog in B needs to be hosted. So to avoid this circular reference issue I tried to define interfaces to grids in third assembly to which A & B both refer, and make B only refers to the interfaces.

Two issues I'm facing:

  1. there’s too much custom data types (properties to be specific) inside the grids which are defined inside A and I have to define interfaces for every one of them.

  2. I see example of this works with function parameter e.g. call target function through the interface passed in. But how would it fit considering the following code - I can't new a ICustomPropertyGridWrapper...

    object = new CustomPropertyGridWrapper(...)
    m_property.SelectedObject = object;

Charles
  • 50,943
  • 13
  • 104
  • 142
Lys
  • 591
  • 2
  • 9
  • 19
  • Does B **require** the classes of A, or is A more like a default usage scenario of utilizing the types in B? If they are tightly coupled, I see no reason to keep them in separate assemblies. – Mark H Aug 17 '10 at 10:11

5 Answers5

5

This is a problem with the language design of C#. In C/C++ you would just use a header to define the interface of the compilation unit and the dependency is resolved.

In C# there are no headers. You have three options

  1. 1> merge the assemblies (increase in compilation time and may not
    make sense if the assemblies are functionally unrelated). C# often forces you to do this, even if the assemblies should logically be separate.
  2. Dependency injection
  3. Creating a third assembly with interfaces which both the modules reference. This accomplishes the dependency injection through a C# language mechanism (interfaces), instead of roll your own; but its the same thing.

Number 3 is typically how these situations are handled in C# but its not as elegant as C/C++ solution to this problem. For large code bases you have to design from the start with this in mind.

HaltingState
  • 1,810
  • 1
  • 20
  • 22
  • I don't see how dependency injection could help here. You still have two assemblies that both want a reference to each other. – Vaccano Jun 20 '13 at 15:45
  • Good pointer on c# limitation of not having a header file. If so, the same applies to Java as well. Not clear how DI can help though. Need an illustration. – liang Aug 21 '13 at 15:05
4

Sounds like you are attempting death by interface. Not everything has to be exposed by interface.

A simple answer is to either merge the assemblies, or move the common controls and data types to a third assembly. You only need to interface things if you want a consistent contractual way to access or work with things, and you want to hide the actual implementation.

slugster
  • 49,403
  • 14
  • 95
  • 145
1

For issue 1, there is not really a solution other then merge the two projects or do some code generation

For the second, you can do that by implementing the Factory design pattern.

Ewald Hofman
  • 12,688
  • 3
  • 39
  • 44
0

Refactor your code or merge assemblies = don't use circular reference. It is symptom of very bad design.

Ladislav Mrnka
  • 360,892
  • 59
  • 660
  • 670
  • 3
    Harsh judgment of the design, considering you know almost nothing about it, and no real advice... I don't think you're being very helpful. – Kobi Aug 17 '10 at 10:05
  • I don't but if you check other answers they are describing the same solution - refactor or merge. So it is helpful enough. – Ladislav Mrnka Aug 17 '10 at 10:09
  • 4
    And it's only a symptom of a bad design. A good design can have symptoms of bad designs, if there's a justification for it, but a good designer will still pay attention to those symptoms and make sure they truly are justified, and that they remain justified as things change. – Jon Hanna Aug 17 '10 at 12:29
  • 1
    There is nothing harsh about this answer. Having two assemblies that reference each other is, at the very least, awkward to work with. – Brian Gideon Aug 17 '10 at 13:25
  • Dont be that sure what is awkard or bad design. Suppose you have a utility assembly called U written with IL and referenced it from assembly A, now you want to write a little utility method in U which has to know about metadata token in A. Considering you have no ability to unload dynamic assemblies in .net core what do you do? – TakeMeAsAGuest Mar 05 '19 at 15:33
0

If B now depends on bits of A perhaps you should refactor those bits out into a new assembly C which would be referenced by both A and B.

ChrisF
  • 134,786
  • 31
  • 255
  • 325