Difference between revisions of "Why is delivery over NuGet feed used for .NET Core?"

From OPC Labs Knowledge Base
Jump to navigation Jump to search
Line 19: Line 19:
 
* You reference the OpcLabs.BaseLib and OpcLabs.EasyOpcUA assemblies from one or more of your project's assemblies. So far so good.
 
* You reference the OpcLabs.BaseLib and OpcLabs.EasyOpcUA assemblies from one or more of your project's assemblies. So far so good.
 
* Right on the next level, the approach will break. We cannot just reference assemblies of OPC UA .NET Stack/SDK, because they are not delivered as assemblies - they are already delivered as NuGet packages. OK - maybe we can try to extract those assemblies from their NuGet package? Yes - but each of them comes in multiple forms, depending on the target platform. Which one should we reference? We do not know upfront... so the only solution would be to build as many forms of our assemblies as there are those of the assemblies we want to reference, and then leave the developer to choose those he wants to reference. This is already bad, because that would force the developer to pick the target upfront - either preventing him/her from building a multitarget solution, or forcing him to build it separately for each possible combination.
 
* Right on the next level, the approach will break. We cannot just reference assemblies of OPC UA .NET Stack/SDK, because they are not delivered as assemblies - they are already delivered as NuGet packages. OK - maybe we can try to extract those assemblies from their NuGet package? Yes - but each of them comes in multiple forms, depending on the target platform. Which one should we reference? We do not know upfront... so the only solution would be to build as many forms of our assemblies as there are those of the assemblies we want to reference, and then leave the developer to choose those he wants to reference. This is already bad, because that would force the developer to pick the target upfront - either preventing him/her from building a multitarget solution, or forcing him to build it separately for each possible combination.
* But it does not stop here. The OPC UA .NET Stack references many pieces of .NET Core and also other NuGet packages (which are not part of .NET Core), and we have no control over them. The other NuGet packages have further dependencies, and so on. The total composition may come to tens or hundreds of modules (that would be the smaller problem), which will differ based on the target operating system and its distribution and version, .NET runtime and its version, and possibly even change over time as new versions of referenced NuGet packages become available.
+
* But it does not stop here. The OPC UA .NET Stack references many pieces of .NET Core and also other NuGet packages (which are not part of .NET Core), and we have no control over them. The other NuGet packages have further dependencies, and so on. The total composition may come to tens or hundreds of modules (that would be the smaller problem), which will differ based on the target operating system and its distribution and version, .NET runtime and its version, and possibly even change over time as new versions of referenced NuGet packages become available. This last aspect the show-stopper - it is realistically impossible to manage - we cannot replicate the logic of this complex fabric of relations on our side and even less maintain it over time. It wouldn't be wise anyway - obviously it is the authors of the referenced packages that can maintain them best.

Revision as of 13:17, 28 August 2018

Effective with version 2018.3, QuickOPC supports development for Microsoft .NET Core. QuickOPC libraries for .NET Core are only delivered through the public NuGet feed (http://www.nuget.org ). This is in contrast to the .NET Framework, where the developer can reference one or more QuickOPC .NET assemblies (there are only 5 or so of them at maximum) that are delivered in product's installation package (and the use of NuGet packages is simply a possible alternative for .NET Framework development). This article attempts to explain why NuGet is the only delivery vehicle for QuickOPC .libraries that target .NET Core.

TL;DR: NuGet feed is used because it is, in our understanding, the only approach that works well for the developer.

Introduction: How it works in .NET Framework

Let's explain the physical composition of QuickOPC when targeting the .NET Framework first. We will explain it on QuickOPC for OPC Unified Architecture, because it is the most relevant aspect needed for comparison with .NET Core. Your project developed with QuickOPC looks like this:

  • You reference the OpcLabs.BaseLib and OpcLabs.EasyOpcUA assemblies from one or more of your project's assemblies.
  • These two OpcLabs.* assemblies only reference assemblies that are part of the .NET Framework itself, and assemblies of OPC Foundation's UA .NET Stack/SDK which are embedded inside the OpcLabs.* assemblies (alternatively, they can be deployed alongside).
  • The .NET Framework, with all its assemblies, is one monolithic piece, sitting pre-installed on the Windows computer (depending on the version, it either comes with the OS or is installed separately).

By shipping a handful of assemblies (in the above example, just OpcLabs.BaseLib and OpcLabs.EasyOpcUA), and instructing the user to have proper .NET Framework installed on the Windows computer, we basically have everything in place to run your project. The number of files we (and you) need to ship is small, stable, and completely predictable.

The .NET Core is different

.NET Core uses NuGet packages as its primary referencing mechanism for itself and all the software that builds upon it, so would almost dismiss the question by saying the using it *is* the way to do things. But there are good reasons for using NuGet on our side as well - in fact, it would be difficult to do it in any other way. With .NET Core, you are entering a landscape that is much more modularized, more diverse, and also dynamic. More modularized: .NET Core does not come in one piece, but in many separate modules that are referenced separately. More diverse: Because it does not run only on Windows, but also on Linux, and other systems - and different distributions and versions of them too. In addition, the modules and their composition and mutual references differ depending on the target system! Dynamic: The referencing mechanism does not necessarily require that precise versions of certain packages and assemblies are always used; for example, newer version of a package can be pulled in if available, and the referencing package allows it.

Let's try to build a QuickOPC project for .NET Core that is equivalent to the .NET Framework project described above, and doing it the same way - by referencing specific assemblies and trying to ship them with the product:

  • You reference the OpcLabs.BaseLib and OpcLabs.EasyOpcUA assemblies from one or more of your project's assemblies. So far so good.
  • Right on the next level, the approach will break. We cannot just reference assemblies of OPC UA .NET Stack/SDK, because they are not delivered as assemblies - they are already delivered as NuGet packages. OK - maybe we can try to extract those assemblies from their NuGet package? Yes - but each of them comes in multiple forms, depending on the target platform. Which one should we reference? We do not know upfront... so the only solution would be to build as many forms of our assemblies as there are those of the assemblies we want to reference, and then leave the developer to choose those he wants to reference. This is already bad, because that would force the developer to pick the target upfront - either preventing him/her from building a multitarget solution, or forcing him to build it separately for each possible combination.
  • But it does not stop here. The OPC UA .NET Stack references many pieces of .NET Core and also other NuGet packages (which are not part of .NET Core), and we have no control over them. The other NuGet packages have further dependencies, and so on. The total composition may come to tens or hundreds of modules (that would be the smaller problem), which will differ based on the target operating system and its distribution and version, .NET runtime and its version, and possibly even change over time as new versions of referenced NuGet packages become available. This last aspect the show-stopper - it is realistically impossible to manage - we cannot replicate the logic of this complex fabric of relations on our side and even less maintain it over time. It wouldn't be wise anyway - obviously it is the authors of the referenced packages that can maintain them best.