0

I have Common.dll that's shared/used by (far more than) two SharePoint packages being deployed to the same GAC used by a single SharePoint instance. The shared assembly evolves from product deployment to product deployment, and it's not treated as a product in and of itself. It is not released, per se. It evolves only in the context of other SharePoint products/packages.

The common assembly is primarily just a repository for highly reusable code. It's used only by a small internal team of developers.

Branching/merging allows various products to take on the latest version of Common.dll whenever it suits the developers. Each product's development effort schedules the risk of taking on the new version of Common.dll.

My need is to have those assemblies act in isolation from product to product -- from SharePoint package to SharePoint package.

But that's not happening. Instead, every time I deploy, Common.dll is overwritten in the GAC such that all products using it receive the behavior of this most recent version of Common.dll. Depending on what that behavior is, it can break a product that hasn't been deployed in some time.

I'm trying to prevent that deployment "surprise!" potential w/o having to treat Common.dll like a public product that has to carefully avoid breaking changes/etc.

What technique do you use to preserve distinct versions of common assemblies when deploying various SharePoint packages to a single SharePoint instance's GAC?

lance
  • 16,092
  • 19
  • 77
  • 136
  • Is each version of Common.dll being compiled with a different version in the 4 part name? – Rich Bennema Apr 18 '12 at 21:05
  • @RichBennema Does this answer your question?: Changing the AssemblyVersion attribute of a dependency assembly between deployments later causes SharePoint Web Part runtime errors. So, the AssemblyVersion of our Common.dll never changes. – lance Apr 18 '12 at 21:34
  • Yes. Installing multiple versions of Common.dll, each with different version numbers, into the GAC is what I would have suggested. – Rich Bennema Apr 19 '12 at 12:08
  • Right. I started there and discovered the runtime error I cited above. That was very disappointing. – lance Apr 19 '12 at 13:20

2 Answers2

0

We use this command in the pre-build event of the common assembly's Visual Studio project:

if not "$(SolutionName)" == "ABC" if not "$(TargetFileName)" == "$(ProjectName).$(SolutionName).dll" exit 1

This pre-build command does not have to change as the common assembly gets consumed by various products. When you replace "ABC" with the name of the common assembly's solution file, it reads like this:

If we're compiling the common assembly in its own solution (which is rare, but it happens), there's nothing to consider -- compile away! Otherwise, fail the build unless someone has renamed the common assembly per the consuming product's Visual Studio solution file name.

To avoid build failure, we rename the common assembly after we branch it into the codebase of the consuming product (via the common assembly project's Properties Pages). The common assembly's project name is not changed in Solution Explorer, nor is its Default Namespace changed in its Properties Pages. Only the "Assembly name" changes. So, except for product-specific changes which have been made, maintaining and consuming the common code always feels familiar: Solution Explorer and namespaces stay the same regardless of the product you're developing.

The rename changes one line in the common assembly's project file, which creates friction as you merge back into the trunk (and/or later, when you merge back out of the trunk into other products).

If the common project file makes its way into the codebase of ProductB while still naming its assembly for ProductA, its pre-build command will prevent compilation in ProductB, where the developers there can easily change the "Assembly name" to allow for compilation. This friction opportunity increases the more you merge.

The common assembly gets a unique name (and instance) in the GAC each time a new SharePoint product arrives in the GAC. Various products can use, evolve, and deploy the common assembly w/o fear of suddenly breaking other products/packages when they deploy.

lance
  • 16,092
  • 19
  • 77
  • 136
  • What happens when a breaking change to the "common" assembly needed by both projects 'A' and 'B' but not 'C' occurs? – Jason Weber Apr 20 '12 at 06:17
  • Make change in ProjectA. Merge Common into trunk. Merge Common trunk up to Project B. Do not merge trunk into ProjectC. Have I overlooked anything? – lance Apr 20 '12 at 15:46
  • It seems to me that this approach trades some versioning-related pain now for ongoing source control pain for the life of the set of projects. The versioning pain can be automated away fairly easily (more detail in my answer). The source control pain will likely only get worse with time and with the number of projects. – Jason Weber May 02 '12 at 03:16
  • Many products branch Common. As that product list grows, the number of changes you must make (to your product's Common project) after merging from Common's trunk does not. If Common's pre-build command prevents compilation of your product after you merge Common from its trunk, you correct Common's assembly name to match your product's solution and compile successfully. That's an annoying, quick, and easy adjustment that won't create SharePoint versioning surprises later (e.g. http://goo.gl/YyJCS ). – lance May 02 '12 at 14:24
0

Versioning and binding redirects may be able to help here. The root issue seems to be the lack of consistent tokenization of strong names by Visual Studio. Rather than creating an elaborate work-around involving source control it might be better to create a simple tool that can update all of the common assembly references in a given project's files. This addresses the root issue without creating other unecessary costs.

Jason Weber
  • 1,472
  • 9
  • 16
  • Considering the binding redirects option: wouldn't that create assembly version differences between the csproj files of Common in ProductA and Common in ProductB (the two branches of Common)? If so, don't those have to be merged at some point (back to Common's trunk)? – lance May 02 '12 at 14:16
  • After a bit of research: The changes I make to SharePoint's web context when configuring assembly redirection are ignored by SharePoint's non-web processes (e.g. timer jobs.. and workflows?). Further configuration effort can (I think) apply the redirection to those processes, also. – lance May 02 '12 at 14:20