Geeks With Blogs

News

Google My Blog


Murray Gordon Flash a-ah! Savior of the universe...

 Question
------
Currently we use two different methods to define references between managed components, namely project references and .NET references to reference assemblies (details below).  Both methods are not fully satisfactory.  We would like to know:
(a) Is there is a better referencing mechanism available in VS8 (better than the ones described below), or
(b) does MS plan to change the support for references in future versions of VS.
 
Example Solution
----------------
ProjectA --> ProjectB
 
The source tree (after building) looks as follows:
Bin
  ReleaseU
    ProjectA.exe
    ProjectB.dll
  DebugU
    ProjectA.exe
    ProjectB.dll
Ref.Net
  (ProjectB.dll)  // only in method 1
ProjectA
  ProjectA.csproj
ProjectB
  ProjectB.csproj
 
There is a example solution added to this case which is more than trivial, but is a good  playground.
 
Method 1: Reference Dlls
------------------------
A reference dll is a copy of the release version of the target assembly, which is checked in like a source file. The source project creates a .NET reference to the reference dll via ProjectA/RightMouseClick/Add Reference/Browse(select b.dll)
In the above example, bin/ReleaseU/ProjectB.dll is checked into Ref.Net/ProjectB.dll. The principle is the same as that used for VB 6 "binary compatibility" dlls.
 
The reference is stored in the project file as follows:

ProjectA.csproj:
    <Reference Include="ProjectB">
      <Name>ProjectB</Name>
      <HintPath>..\Ref.Net\ProjectB.dll</HintPath>
      <Private>False</Private>
    </Reference>

Method 2: Project References
----------------------------
A project reference is stored in the project file of the source project in the following format:
 
ProjectA.csproj:
    <ProjectReference Include="..\ProjectB\ProjectB.csproj">
      <Project>{17A348DA-0AFB-46C8-9FBA-9DAC268BE117}</Project>
      <Name>ProjectB</Name>
    </ProjectReference>

Using project refererences, the developer of ProjectA has to have ProjectB in his solution, even if he does not develop ProjectB himself. In the case of PUMA this means that the average solution of a UI project has some 30-40 projects.
 
Pro/Cons of Reference Dlls
--------------------------
+ The developer of ProjectA does not need to include Projects B in his solution, unless he wants to debug it.
- The developer of ProjectB has to update the reference dll when he changes a visible (public or protected) member.
- The reference dll has to be locally available on the development machine (can't use "T"-drive to build machine).
 
Pro/Cons of Project References
------------------------------
+ No additional reference dlls are necessary.
- The developer of ProjectA has to include ProjectB (and all components that ProjectB depends on), even if he does not want to build or debug them.
- When the developer of ProjectB add a reference (e.g., ProjectB -> ProjectC) the solution for ProjectA fails to build.
- When the project GUID changes, solution files that include the project have to be updated.
- The complete source of all projects that ProjectA depends on has to be available on the developers machine.
 
In the ideal world...
To combine the advantages of project refs (no copying of dlls) and project references (small solutions) we would like a reference definition like the following:
 
ProjectA.csproj:
    <Reference Include="ProjectB" </Reference>

To locate the actual dlls, we want to be able to specify a configuration-specifc reference path on the project level, e.g.
 
    <ReferencePath>
        Release="..\Bin\ReleaseU; T:\bin\ReleaseU"
        Debug="..\Bin\DebugU; T:\bin\ReleaseU"
    </ReferencePath>
 
Close Solution with VS7
-----------------------
We had a near solution with VS7, but it was only near and seems
not to work with VS8 anymore:

With VS7 we found out that there is a folder in registry
HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\VisualStudio\7.1\AssemblyFolders\<Product>
which's content is searched for assemblies need to satisfy .net references

But with VS8

  • The above location is gone
  • It is not referenced during compilation (We sniffed via Regmon during compilation)
  • If the above folder exists it does not address the need of configuration specific dependencies

Big Picture
-----------
We have learned from out c++ past, that it is important  to give developers so called sandboxes, and this means
that they only have a part of the source tree locally, work on it compile it, and the rest of the components is somewhere on the net, and is referenced via a net  work drive. The network drive with all other components is the overall source tree, which is the output of daily build, so it is uptodate

This simple pattern can not be followed with the current version of VS8, and I guess this will hit everyone
else, who does not small projects.


3 Methods Available to Reference other code in Visual Studio 2003 and Visual Studio 2005

There are 3 methods available to reference other code in .NET (VS 2003 and 2005): project references, assembly reference and web references (web services, etc.)  For non-web references you are still limited to project and assembly referencing. 

Each type has its own usages.  All-in-all project references are the best because they remove any maintenance work needed whenever the referenced assembly changes.  You just see the changes.  Unfortunately, as you mentioned, project references require that the project be included in your solution.  This adds undo compilation (even if the source hasn't changed), increases the size of the solution and requires the source code.  Project references are best used for projects that you'll have to build anyway.

Assembly references are used for third-party components and for projects that you don't build in your solution directly.  This is commonly done for large products that would have hundreds of projects.  There is no benefit in putting them all in a single solution if no one developer would ever be working on them all.  Unfortunately assembly referencing requires that you keep the referenced assembly up-to-date with the builds.  VS won't necessarily recompile your code just because a referenced binary changes.

For assembly referencing however  you can store the assembly in one of three places: GAC, locally in the project or in an arbitrary location on disk.  For signed assemblies you should retrieve them from the GAC.  For third-party components you should store the assemblies in a dedicated directory under your solution so that all projects can reference the same binaries.  I personally create an "Assemblies" directory under my solution and any referenced assemblies go there.  They may or may not be in CM depending on whether they come from an installed product or not.  Finally note that referencing assemblies from a network drive also works assuming you can get to the assembly at compile time. 

Note that assembly referencing is actually a good thing because you can tell VS to target a specific version.  This gives your app the side-by-side versioning support that it needs.  If a third-party component you use ships a newer, buggy version you can just tell VS to use the previously unbuggy version instead.  You can't do this with project references.

There is a setting in VS 2003 that was moved in VS 2005 to References tab in the project settings.  Although I believe this only specifies what paths to search when using the Add Reference option.  As far as finding the reference once it is added to the project it is irrelevant because when you add the reference VS stored the location of the original reference so it knows where to find it.

So, in a nutshell there are only 2 referencing options: project and assembly.  Prefer project references when you are building the code already in your solution.  It removes the requirement for validating dependencies.  Use assembly referencing in all other cases and use either the GAC, the installation directory for commercial assemblies or a dedicated assembly directory for your own components.  Don't forget to update the references and rebuild whenever the external assembly changes.

Added Notes:

I personally prefer the assembly reference pattern, because don't need to have everything in my solution, and solutions can be big.

The missing point for me is to specify more than one location for a already-but-not-by-me-built-assembly. I would like to give at least two locations for such an assembly. One one the network drive and one on my local drive. Because this would enable me to continue my sandbox pattern:

There is a nightly build, which compiles the whole source tree, even the base components, and shares the compiled source under a share.

Furthermore there is the 'sandbox' source of a developer on a local computer, which is only a subset of the whole source tree. So the developer does changes to components on his local source base,  compiles, and to successfully compile needs a so called base-lib, because his components have a assembly reference to this base-lib. Unfortunatley she does not have the base-lib not on the local disk so the compilation would fail. If we now had a mechanism,  which runs through the possible locations for a base-lib, it would find the needed assembly at least on the network drive ( because we sepcified so ) But it could also be found on the local drive, if the developer copied the base-lib manually from the somewhere to his own Assembly folder.

Maybe I can have comma seperated list in
<HintPath>..\Ref.Net\B.dll</HintPath> the .csproj, but it is cumbersome to manually add entries here. The IDE should support so called 'alternativ assembly reference locations'

Solution:

There there is also a way for multiple location for your build to look when compiling. You can to do this by modifying the <HintPath> in the project file. For example, In Notepad, open up your .csproj file and edit the following line(s):
      <HintPath>..\<Path>\bin\debug\<AssemblyName>.dll</HintPath>
to say this instead:
      <HintPath>..\<Path>\bin\$(Configuration)\<AssemblyName>.dll</HintPath>

This would make sure that the assembly corresponding to the active configuration is being picked up by the reference manager.

This info was compiled from a great thread on Microsoft Forums: http://forums.microsoft.com/msdn/ShowPost.aspx?PostID=117743

 

I thought this was great information and very helpful for anyone dealing with large development teams and finding solutions to builds that don't require costly addon or 3rd party build packages.

Thanks,
Murray

Posted on Tuesday, October 25, 2005 9:41 PM | Back to top


Comments on this post: Visual Studio 2005 Reference Types for multiple build configurations and multiple assembly locations

# re: Visual Studio 2005 Reference Types for multiple build configurations and multiple assembly locations
Requesting Gravatar...
Murray,

I thought you may like to know that you can still use the registry edit to make assemblies appear in Visual Studio 2005. There is just a different area in the registry to add the folder to look for to.

HKEY_LOCAL_MACHINE\SOFTWARE\Microsoft\.NETFramework\v2.0.50727\AssemblyFoldersEx

Add your Key there with its REG_SZ data pointing to the folder your built assemblies are in and they will show up.

Sincerely,

Justin
Left by S. Justin Gengo on Nov 30, 2005 6:11 PM

# re: Visual Studio 2005 Reference Types for multiple build configurations and multiple assembly locations
Requesting Gravatar...
Thanks for the info. You rock!

~Murray
Left by Murray on Dec 01, 2005 5:43 AM

# re: Visual Studio 2005 Reference Types for multiple build configurations and multiple assembly locations
Requesting Gravatar...
Thanks buddy. It will help me..
Left by shrikant Landge on Feb 05, 2009 12:45 PM

# re: Visual Studio 2005 Reference Types for multiple build configurations and multiple assembly locations
Requesting Gravatar...
That also helped me out a lot. Thanks.
Left by Daniël on Nov 06, 2009 10:12 AM

Your comment:
 (will show your gravatar)


Copyright © Murray Gordon | Powered by: GeeksWithBlogs.net