Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Best way to maintain .NET project dependencies and updated binaries in large multi solution application

I know this is a vague question, but I spent hours of searching and couldn't find a solution. I have a class library project - A I have another class library project - B B has a reference to A I have another console application project - C C has a references to both A and B.

Now, what happens is: A's code is being updated. A is being rebuilt. Now B needs to get that new A binary, and then B needs to be rebuilt. Now C needs to get that new A binary AND that new B binary.

Now imagine that I maintain several projects, each in its own solution, and that chain of dependencies is longer.

What is the best way to maintain all those binaries and keep them up to date?

How can I make sure that C always has the most up-to-date versions of A and B?

One solution I found is to create a nuget server in which there will be a nuget package for A and for B, and when A or B's binaries are updated, new nuget packages will be rebuilt, and because C will use these nuget packages, it will always have the most up-to-date binary versions of A and B.

We work with SVN but I don't see how it can help managing dependencies between projects.

Any suggestion/direction will be very helpful Thanks

like image 348
Alonzzo2 Avatar asked Oct 22 '17 11:10

Alonzzo2


People also ask

How do I add support for a multi-targeted.NET Project?

The following sections describe several ways to add support for .NET based on the example repository. Replace existing projects with a multi-targeted .NET project Reorganize the repository so that any existing *.csprojfiles are removed and a single *.csprojfile is created that targets multiple frameworks.

How do I add a dependency to an existing project?

Add a dependency by editing the project file To add a dependency, add a <PackageReference> element inside an <ItemGroup> element. You can add to an existing <ItemGroup> or create a new one. The following example uses the default console application project that's created by dotnet new console:

What should I do with my existing projects in NET Core?

Keep existing projects and create a .NET Core project. If there are existing projects that target older frameworks, you may want to leave these projects untouched and use a .NET Core project to target future frameworks. Changes to note are: The .NET Core and existing projects are kept in separate folders.

Can I create a solution that compiles for both net and framework?

You can create a solution that compiles for both .NET Framework and .NET side by side. This article covers several project-organization options to help you achieve this goal. Here are some typical scenarios to consider when you're deciding how to set up your project layout with .NET.


2 Answers

The dependency chain you are describing is handled differently in different Visual Studio versions what depends on type of the project you are using. In old C# project version (pre VS 2017) when project reference is used (it is displayed in meta folder of the project as a references) and Visual Studio is unable to track and copy dependencies of project reference. This is why it was necessary to have your project C to reference both project A and project B.

Whereas in new format of csproj in Visual Studio 2017 when dependencies are used instead of references MSBuild is capable of traversing whole dependency tree and will handle properly situation where your project C references only project B which references project A. All required by application assemblies will be built and copied into output directory of project C.

In both cases there is no need to use NuGet server.

Now imagine that I maintain several projects, each in its own solution, and that chain of dependencies is longer. What is the best way to maintain all those binaries and keep them up to date? How can I make sure that C always has the most up-to-date versions of A and B?

Once you have broken your dependency chain handled easily by MSBuild by separating your projects into separate solutions your build system lands in unsupported directly by Visual Studio territory. For pure managed .NET applications I would avoid that at any cost. For examples of building large, complex managed projects have a look at Roslyn compiler.

To solve that problem without using NuGet server at all - and it is my recommendation - you can create tree of dependencies spanning through solution boundaries by referencing directly from projects of one solution their dependencies (projects) from another solution. This will make your build much easier to manage (and it is particularly important for CI and DevOps solutions) and expand.

If you cannot modify current project/solution structure just create a new one as an overlay over existing project/solution structure and configure it properly. You will end up with one solution/project system which is perhaps easier to work with during code editing and testing and a second one which spans all maintained projects which is better suited for building whole application.

If the above option is not working just modify your all projects to output all final artifacts to one common output directory (move bin of every project to common top level bin directory, you may want to move obj intermediate directories as well).

If the choice of the NuGet server is a must the easiest way to do it it is to use common output directory and use NuGet.config in all projects consuming dependent projects by pointing them to new package source.

<?xml version="1.0" encoding="utf-8"?>
<configuration>
  <!-- NOTE: Leave this file here and keep it in sync with list in dir.props. -->
  <!-- The command-line doesn't need it, but the IDE does.                    -->
  <packageSources>
    <clear/>
    <add key="private NuGet" value="file:///e:/src/myproject/.nuget" />
    <add key="nuget.org" value="https://api.nuget.org/v3/index.json" />
  </packageSources>
  <config>
    <add key="repositoryPath" value="..\packages" />
  </config>
  <packageRestore>
    <!-- Automated package restore in VS does not work at this time with
         this project and it causes build failures in VS. Disable it. -->
    <add key="automatic" value="false" />
  </packageRestore>
</configuration>

In the above NuGet.config file:///e:/src/myproject/.nuget points to main directory of your NuGet server (simple file system directory) where all .nupkg(s) are stored - it will require setting common output directory for nupkg(es) from all projects. This will not work on network shares yet as this nuget.client feature is under development right now. See nuget.clinet pull request which is still open at the time of writing Adding support for Network Share Hosted Package Source and compatability with generic build tools.

If you want to use full blown NuGet server first I would seriously consider using it as an external service i.e. myget.org. They have free plan if your packages can be public or paid plans if you want to keep your packages private.

Finally if you want to use your very own NuGet server go to NuGet project site and choose one you would prefer. NuGetGallery - equivalent to current nuget web site or smaller one NuGet.Server and follow installation instrcutions.

like image 54
Jacek Blaszczynski Avatar answered Oct 17 '22 04:10

Jacek Blaszczynski


I have my own local NuGet repository so I think that my method should work on some shared network disk where you will have newest nuget packages.

First you need to install nuget standalone. You will download it from official website and you will have nuget.exe. I suggest adding it to the folder which will be added to system PATH environment variable. By doind this it will be accessible from your computer everywhere just by typing 'nuget'.

  1. Now you need to get to the folder where is your .csproj file from your library.
  2. Initialize your .nuspec file by typing nuget nuspec
  3. You should have file [project_name].nuspec. Open it and add this line as second line of file after <xml> tag. It's weird that nuspec do not add this automatically.

<package xmlns="http://schemas.microsoft.com/packaging/2012/06/nuspec.xsd">

  1. authors tag and description tag on my computer could not be fetched from .csproj file so i needed to input values there manually.
  2. I defined post-build event to my .csproj file as this: nuget.exe pack $(ProjectPath) -IncludeReferencedProjects -OutputDirectory "D:\programowanie\nugetPackages" powershell.exe D:\programowanie\nugetPackages\install.ps1

First command packs your project files into .nupkg files and send them directly to nugetPackages folder on disk D (there you could use some shared network drive).

-IncludeReferencedProjects description from specification: Indicates that the built package should include referenced projects either as dependencies or as part of the package. If a referenced project has a corresponding .nuspec file that has the same name as the project, then that referenced project is added as a dependency. Otherwise, the referenced project is added as part of the package.

  1. Install.ps1 contents:

nuget init D:\programowanie\nugetPackages D:\programowanie\nugetServer\

It creates folder structure in NugetServer directory for my packages and copy .nupkg files to those folders.

  1. Now you need to add new package source inside your viual studio. You just enter path to the D:\programowanie\nugetServer\ in my case and name. You do it here:

  2. I created solution for my .csproj library. I do not know if I done it by accident or is it really needed.

It was my first approach to having my own nuget package folder to maintain dependencies. I think that my solution is still not very good and lack a lot of automation. If you would like to have more info on the topic i suggest to stick with oficcial guidelines.

I do not have so complicated dependencies as in your case. But maybe creating solution which includes all of those libraries and definining good build order will enable to automatically build and deploy them to nuget server with my method.

like image 27
Shoter Avatar answered Oct 17 '22 05:10

Shoter