(I think the problem described below is also affecting VS although I only tested it in MD)

I have some trouble regarding circular dependencies. I know they are bad practice and should be avoided. In recent MonoDevelop Releases, you can't even create circular dependencies. However, I can't find an easy way out in the following Scenario:

Application A uses the managed extensibility framework (MEF) to dynamically add functionality via Plugins, which can be developed by 3rd parties, and are loaded by just placing the .Dll into the bin/ folder (DirectoryCatalog in MEF terms).

As I am the Developer of Application A, I ship some default Plugin(s) along with my application. Plugins may deliver LOTS of functionality to extend Application A, so I have every Plugin in a new .csproj Project.

To develop a plugin, one (myself or any other 3rd party) must implement a class that implements an interface. The interface, lets call it Interface A, is defined in Application A and is less than 50 lines of code. Thus, Plugin A requires Application A as a dependency, because Interface A is defined in the Assembly of Application A. Since I want to use the Plugin A in my Application A, I add it as a reference, too. And voila, there is a cross reference between the two.

I've come up with solutions, but I am not happy with them:

1) Create a seperate project and put ONLY the interface file in it. I dislike that because I don't see a 50line .cs to be a seperate project and consider this as "over-modularization"

2) Do not reference the Plugin at all within Application A (this is possible, as Application A only uses Interface A - the actual class instance is loaded by MEF).

This, however, leaves me with some trouble:
I cannot work on Application A and easily go to the code of Plugin A to fix sth. or add a feature which I often do - because I load core functionality into Plugins (one of the main goals of MEF is to allow modularization). I could however, start a 2nd instance of VS / MD. But this gets bad the more plugins I add, I will end up having 10 instances of IDEs open - I doubt any machine could handle this.

1 Answer
1

(In this example, Plugin1 is has extension points, and Plugin2 extends both ApplicationA and Plugin1.)

So, ApplicationA, Plugin1, and Plugin2 all have a dependency on ApplicationA.Contracts.

Plugin1 and Plugin2 also have dependencies on Plugin1.Contracts.

The .Contracts assemblies only have the interfaces, or possibly some helper base types in there too. Yes, it's OK to have a small assembly with just the interfaces in them. That ensures that Plugin1 won't break when you change an implementation detail in ApplicationA, and vice-versa.

If you have common "helper stuff" that both ApplicationA and Plugin1 both need, put those in a separate Utilities assembly and have both reference it.

The assembly declaring the extension point (ImportMany in MEF terms) should never have a reference to the assembly extending that extension point (the plugin). Therefore, AssemblyA should never reference Plugin1 or Plugin2, and Plugin1 should not reference Plugin2.

do you mean to have seperate projects (.csproj) for each of your bullet points? Because that would mean I'd have a project only for the ApplicationA.Contracts which I wanted to avoid.
–
DynaJun 17 '11 at 16:28

@Dyna - yes, that is the best way to do it, in my experience. You do know that you can put all the .csproj into one solution and have them all open at the same time, right?
–
Scott WhitlockJun 17 '11 at 16:45