A quirky way to handle dependencies on artifacts from other solutions
Say you’ve got two big .Net solutions:
- Enormous legacy codebase including lots of patterned, reusable code (200 projects)
- Internal dependencies which cascade; i.e. WarehouseService depends on WarehouseBusinessModel depends on WarehouseDataModel
- New front layer partially dependent on the old modules (20 projects)
- To avoid repeating yourself (and to avoid functional shortfalls of a rewrite) you rely on WarehouseService and a bunch of its siblings
Now, Solution 2 needs some way of importing the WarehouseService library. If you include the WarehouseService project into Solution 2, you also have to include all of its dependency projects, leading to a solution as big as, or bigger than, Solution 1. Big solutions are painful!
The right way
There is a “correct” solution to this problem, which is to use artifact repositories like local Nuget. Azure DevOps Artifacts is made for this. Your cloud build (Azure Pipelines etc) does a Nuget Pack operation and pushes the output into some repo in the cloud, and you have Solution 2 depend on those Nuget packages. That is how to do this.
I wrote previously about how to publish your first Nuget package, including how to use a local folder as a repo.
But if you can’t do that for whatever reason, we can be inventive!
You might try adding the DLLs from the Debug/Release/Whatever folder of WarehouseService et al into your project as References. That will produce something like this in your csproj:
<Reference Include="Biz.Core.BusinessModel"> <HintPath>..\Biz.Core.BusinessModel\bin\Debug\Biz.Core.BusinessModel.dll</HintPath> </Reference> <Reference Include="Biz.Core.DataModel"> <HintPath>..\Biz.Core.DataModel\bin\Debug\Biz.Core.DataModel.dll</HintPath> </Reference>
This is fragile, because it will only work when the dependency was built in Debug config. On your CI/CD build server, you should be building in some kind of Release mode. If you say, “Fine, I’ll make the DLL reference
\Release\”, you won’t be able to test it in Debug mode! So this isn’t going to work long-term.
The crux of my quirky solution is to make use of the VS/MSBuild variables available at build-time. We can manually edit the
csproj files to change
Debug in every internal reference to
<Reference Include="Biz.Core.BusinessModel"> <HintPath>..\Biz.Core.BusinessModel\bin\$(Configuration)\Biz.Core.BusinessModel.dll</HintPath> </Reference> <Reference Include="Biz.Core.DataModel"> <HintPath>..\Biz.Core.DataModel\bin\$(Configuration)\Biz.Core.DataModel.dll</HintPath> </Reference>
VS will be totally happy with this and will continue to show the References’ properties correctly in the Properties window, reflecting the config which is currently selected.
To build in Debug mode, you have to build Solution 1 in Debug mode first. You don’t have to keep its VS window open if you’re not making changes; just build it once and hack on Solution 2 all day.
To build on a server, like AzureDevOps/TFS, you need a Visual Studio build task for Solution 1 first, follwed by a Visual Studio build task for Solution 2. They both have to be set to the same Configuration.
Go the right way if you can, but if getting dozens of projects into a Nuget repo and using them is impossible, I hope this trick helps you.