views:

620

answers:

3

I have a Java background so I’m used to having Maven handle all problem around downloading and keeping dependencies up to date. But in the .NET environment I have not yet found a good way to manage all these external dependencies.

The main problem here is that I mass produce solutions and they all tend to depend on the same third party dll’s. But I don’t want to maintain separate copies of each component under each solution. So I need a way of linking all the different solutions to the same set of dll’s.

I realized that one solution might be to include the external libraries in a ”library project” that is included in all solutions and let the other projects references them through it. (Or just make sure to reference the external dll’s from the same place for all projects.)

But are there any better ways to do this? (Preferably using some sort of plug-in for Visual Studio.)

I’ve looked at the Visual Studio Dependency Manager and it seems like a perfect match but have anyone tried it for real? I’ve also seen the .NET ports of Maven, but unfortunately I was not too impressed by the status of those. (But please go ahead and recommend them anyone if you think I should give them another try.)

So what would be the smartest way to tackle this problem?

Update:

I realized that I needed to explain what I meant with linking to the same set of dll’s.

One of the things I'm trying to achieve here is to avoid that the different solutions are referencing different versions of each component. If I update a component to a new version, it should be updated for all solutions upon next build. This would force me to make sure all solutions are up to date with the latest components.

A: 

I usually have a separate folder structure on the source control for extrenal or Internal dependencies, and these filders have the assemblies according to build or version number for example

public\External\libraries\Nunit\2.6\

or

Public\Internal\libraries\Logger\5.4.312\

and inside the solutions all the projects that need to use any of the dependencies just adds a reference to that assemblies in the public internal or extrenal folders.

bashmohandes
+2  A: 
  1. Find some place to store the assemblies. For example, I store the .Net core assemblies like so:

    • <branch>\NetFX\2.0527\*
    • <branch>\NetFX\3.0\*
    • <branch>\NetFX\3.5\*
    • <branch>\NetFX\Silverlight 2\*
    • <branch>\NetFX\Silverlight 3\*
  2. Use the ReferencePath property in MSBuild (or AdditionalReferencePath in Team Build) to point your projects at the appropriate paths. For simplicity and easy maintenance, I have 1 *.targets file that knows about every such directory; all of my projects Import that file.

  3. Make sure your version control strategy (branching, merging, local<->server mappings) keeps the relative paths between your projects & your reference paths constant.

EDIT

In response to the update in the question, let me add one more step:

4) Make sure every assembly reference in every project file uses the full .Net strong name and nothing else.

Bad:

<Reference Include="Microsoft.SqlServer.Smo">
  <SpecificVersion`>False</SpecificVersion>
  <HintPath>..\..\..\..\..\..\..\Program Files (x86)\Microsoft SQL Server\100\Shared\Microsoft.SqlServer.Smo.dll</HintPath>
</Reference>

Good:

<Reference Include="Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91, processorArchitecture=MSIL" />

Advantages of the latter format:

  • Using a HintPath in a collaborative development environment will inevitably lead to situations where "it works for me" but not others. Especially your build server. Omitting it forces you to get your reference paths correct or it won't compile.
  • Using a weak name invites the possibility of "DLL hell." Once you use strong names then it's safe to have multiple versions of the same assembly in your reference paths because the linker will only load ones that match every criterion. In addition, if you decide to update some assemblies in place (instead of adding copies), then you'll be notified of any breaking changes at compile time instead of whenever the bugs start coming in.
Richard Berg
Yes, of course, MSBuild. I guess it was only a matter of time before I had to learn how to use it... ;)This sounds like a good general solution but I'm still open for other suggestions.
Ola Herrdahl
See my update to your update.
Richard Berg
Thanks, this helps, although one of my issues are that I'm forced to use weak names for some dependencies. E.g.http://mef.codeplex.com/Thread/View.aspx?ThreadId=57524 (I'm not quite ready for the .NET 4.0 beta yet.)So this is the heart of my problem, but now it is probably solvable. I just need to write a script that finds and removes all local assemblies in a solution making sure it can only reference assemblies pointed out by the ReferencePath property.
Ola Herrdahl
Yes, if the project is big enough to have multiple developers and multiple external dependencies, being able to build it with MSBuild or MS Team Build is well-nigh essential. A side note about using strong names: I've seen people get into trouble because they were using weakly-named <Reference>s to other (sub-)projects instead of using <ProjectReference>. If you have a dependency on some other project (e.g. DLL) being developed by your team, it's better to have the code in the same source tree (or use svn:externals) and use a <ProjectReference>, for the same reasons Richard enumerated above.
Daniel Pryden
+1  A: 

Adding to what everybody else is saying, it basically comes down to two things:

  1. Making sure that all developers have the same versions of external libraries
  2. Making sure that all developers have the external libraries located in the same place (at least, relative to the source code)

As Richard Berg points out, you can use ReferencePath and/or AdditionalReferencePath to help solve #2. If you're using msbuild in your build process (in our case, we're using CruiseControl instead of MS Team Build), you can also pass ReferencePath to it on the command line. To solve #1, I've found svn:externals to be useful (if you're using SVN).

My experience with Maven is that it's way overkill for most purposes.

Daniel Pryden
Yes, actually this is almost what I'm doing right now. I'm using svn:externals to include other common things for all solutions. This is probably a great solution in most cases and would be my fallback for the dependencies too. But still, I want a faster/easier way to manage dependencies, preferably without having to store them in SVN at all. I just tried the Visual Studio Dependency Manager and it gives me the speed I’m looking for while managing dependencies (drag and drop from a repository and a one-click to update to latest).
Ola Herrdahl