Click to See Complete Forum and Search --> : Circular dependencies


Satishpp
March 10th, 2005, 02:30 PM
Hi Gurus,

My post below is quite long, but I could not find any way to explain my problem without giving some background. Any comments would be most valuable.



I have a windows forms application, that has 3 projects.

1) Windowsapplication - This holds the MDI parent form
2) ClassLibrary1 - This holds various forms that are opened as child forms within the MDI
3) BaseLibrary - this holds the baseclasses for forms in ClassLibrary1. (FrmBase and FrmModalBase)

So at this point, WindowsApplication has a reference to ClassLibrary1 and BaseLibrary
and
ClassLibrary1 has a reference to BaseLibrary and all is well in my app.


Now, I have a requirement for all forms in ClassLibrary1 that inherit from FrmBase to have a button which when clicked will show
a modal form displaying some data. Since the data on the form is going to be the same irrespective of which form I call it from, I
decide to put this button on Frmbase. Note that the modal form that is to be called is in ClassLibrary1.

My above solution to put the button on FrmChildBase cannot be implemented because this would need BaseLibrary to have a reference
to ClassLibrary1, which would create a circular reference. I tried this and VS.net gave me the following error message -
"A reference to project "ClassLibrary1" could not be added. Adding this project as a reference would cause a circular dependency"

I thought that was the end of this idea and that I would have to come up with a different way to do this, when another developer
came up with a way to solve this. Here is what he does:

1) Get the reference path for ClassLibrary1 from the WindowsApplication project. Let say this is the path -
"C:\MiscTests\WindowsApplication\ClassLibrary1\obj\Debug\ClassLibrary1.dll"

2) Now in BaseLibrary right click to add reference, click browse and type in the file path above and click OK

This way, vs.net does not complain about a circular reference. I tried this and it works as desired.

Now my question is a) why does this work, when it really is a circular reference. b)It my work now, but will it cause some other problem - Say a memory leak?

I have attached a stripped down example. It has no real functionality, but demonstrates the app working with the circular refernce. You will need to create a folder called misctest under c: and extract the zip there, since the reference path is hardcoded.

Thanks
Satish

enfekted
March 10th, 2005, 04:49 PM
If ClassLibrary1 is compiled first, it will be compiled against a pre-compiled version of BaseLibrary. This could (and probably will) cause runtime errors when trying to access a method that may no longer exist. The same would go if BaseLibrary is compiled first.

What I usually do is have 3 assemblies for large projects. An assembly that contains only the entry point (and maybe some configuration & loading stuff), an assembly that contains only UI (WinForms and embedded graphics), and one that contains all the data manipulation & storage classes.

If your having a problem with circular dependency then you may want to look at the purpose for each of your assemblies and figure out if you're staying within these boundaries. Its really easy to just create classes wherever without thinking which assembly its supposed to go in.

Hope this helps.

Issa
March 10th, 2005, 05:48 PM
in the case that VS does not let you set references between projects, this does not actually reflect any real circular dependency. in other words, VS will not allow you to establish a direct circular reference between projects, regardless of whether the code in the projects actually depends on the reference.
as far as actual circular references in your code (as opposed to the superficial check VS did above), it is certainly possible to create these without causing problems. after all, it is just a type of recursion.

an obvious significant problem we associate with circular references is that if they exist they may cause an infinite regression while the computer attempts to resolve references. despite your circular reference, this does not occur because your modal form is not automatically being instantiated with a form from ClassLibrary1. hence, there is a finite sequence of operations that must be performed to define the state of a ClassLibrary1 form at instantiation. if you were to change your code (i havent really read it) so that instantiation of FrmBase automatically instantiated a derived ClassLibrary1 form, you should get a stack overflow error. this time the error arises because the existence of a ClassLibrary1 form directly implies the existence of a distinct FrmBase instance, implies the existence of a new distinct ClassLibrary1 form instance, and so forth, ad infinitum.

edit: i should note that you might want to reconsider your design. :)

enfekted
March 10th, 2005, 06:11 PM
Just to go into more detail from my prior post...

If Library1 has a project reference in VS to Library2. And Library2 has a direct reference to "Library1.dll" (the output of Library1), then Library2 will almost always be built against an out-of-date Library1.


If Library1 is being built than VS will require Library2 to build first since there is a Project reference.
Library2 will then copy over the already existing Library1.dll from the last time Library1 was built and do compilation checks against the classes and method difined in the old version of Library1.
Then Library1 will be built against the new version of Library2.

If something were to be changed in Library1 that should cause a compilation error in Library2, I don't think Library2 will catch it until the 2nd time it is built because the 1st time it would be using the "library1.dll" from before the changes were built.

Satishpp
March 11th, 2005, 09:30 AM
Thanks for your replies - enfekted and Issa.

I have been thinking about this problem since yesterday and was begining to come to the same conclusion that I need to rethink my design.

I have decided to put the modal form in the baseLibrary itself. It goes against the basic rule we had established in our project group that the baselibrary should only contain bases classes that will be derived from, but I think this is a good case to bend the rule, since the modal form will only be called by the ChildBase form.

Thanks for your help again.

-Satish