4

Is it possible to put in place automatically enforced restrictions on the dependencies allowed between projects in Visual Studio?

For example, say I have three simple layers; UI, Business and Data. Can I enforce that UI should never hold a reference to Data and stop the solution from building if such a thing were to happen?

I'd expect a persistent developer to be able to get around this but can see the benefits of it in terms of guiding developers and detecting mistakes early on.

Craig Bovis
  • 2,720
  • 3
  • 26
  • 33
  • loose coupling. MEF is your answer. – JSJ Jan 23 '13 at 11:54
  • Care to elaborate @Jodha? – Craig Bovis Jan 23 '13 at 11:57
  • 2
    If you can't catch at compile time, you may be able to catch at check-in time. Also there's NDepend ([usage example](http://stackoverflow.com/questions/304967); [another](http://www.gamlor.info/wordpress/2011/03/ndepend-creating-dependency-violation-warnings/)), but it may be overkill for your requirements (although I realise your question text is just an illustration). – AakashM Jan 23 '13 at 12:04

3 Answers3

2

You can't directly or forcibly prevent references, but what you can do is set up the references yourself, this will help with your scenario because people will not be able to add references back (hard circular references). This doesn't stop people using libraries like MEF or Unity from jumping around in a very loose decoupled way - it is entirely possible that they resolve or load assemblies that you don't expect and call in to them (I call this a logical circular dependency). The only way to guard against this is vigilance via code reviews.

Once you have your references correctly set up you can then monitor the changes to the project files to tell when other hard references have been added. Any source control system makes version compare trivially easy, and some (i.e. TFS) will even allow you to be notified when specific files are changed (like when a project file is changed).

Once again, the surest option you have is code reviews.

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

I've just downloaded Ref-Restrict for Visual Studio, via Nuget. Seems to be ok for now.

It examines the references of every project, checking them against a custom set of rules (restrictions). When the solution or project is built, the build will stop if there are any violations. The exact problem will be reported as a build error in Visual Studio.

The config look like this:

<rrconfig>
  <!-- The core library should have no local dependencies -->
  <!-- Data access libraries should not be included as data access should be in the data library -->
  <rules project="RR.Core">
    <nolocalrefs/>
    <exclude>EntityFramework</exclude>
    <exclude>EntityFramework.SqlServer</exclude>
  </rules>

  <!-- The data library should only have access to the core library and no other local libs. -->
  <!-- Data access libraries should definitely be included -->
  <rules project="RR.Data">
    <onlylocalrefs>
      <project>RR.Core</project>
    </onlylocalrefs>
    <include>EntityFramework</include>
    <include>EntityFramework.SqlServer</include>
  </rules>
</rrconfig>

Blog: http://www.benibinson.com/blog/2014/8/31/restrict-project-references-with-ref-restrict

Source and install instructions: https://github.com/CodeHex/Ref-Restrict

Thierry_S
  • 1,526
  • 16
  • 25
1

You could prevent the project from building if an unwanted assembly is referenced, but if that can only be accomplished by means of some external tool, then you have to consider the relative merits of complicating your build procedure for this check.

It might be better to programmatically fail the startup of your application if an unwanted assembly is referenced.

The following code:

Assembly.GetExecutingAssembly()
        .GetReferencedAssemblies()
        .Select( a => a.Name )

will give you the names of all assemblies referenced by the currently executing assembly. Then, you can check whether this list of names contains the name of the unwanted assembly.

For details, see https://stackoverflow.com/a/72460117/773113

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142