Differentiating assemblies by publicKeyToken alone - versioning

Consider the following scenario:
A NuGet package contains two versions of an assembly, one for .NET 3.5 (in lib/net35) and one for .NET 4.0 (in lib/net40). Both are named SomeInterfaces.dll and have version 1.0.0.0, but the strong names for the two assemblies have different publicKeyToken values.
An application named CoolProgram.exe exists, and exposes extensibility features (e.g. via MEF)
Company A develops an extension AExtension.dll and references the .NET 3.5 version of SomeInterfaces.dll.
Company B develops an extension BExtension.dll and references the .NET 4.0 version of SomeInterfaces.dll.
One of the following is provided:
The extensions AExtension.dll and BExtension.dll are placed in the same folder as CoolProgram.exe, and the two copies of SomeInterfaces.dll are placed in the GAC.
The application adds the paths where extensions are installed to the CLR binding path. For example, AExtension.dll and SomeInterfaces.dll (.NET 3.5) could be placed in the directory extensions/A, and BExtension.dll and SomeInterfaces.dll could be placed in the directory extensions/B; both of these two directories are placed in the binding path of the application CoolProgram.exe.
Questions:
In situation 5.1:
Will CoolProgram.exe be able to load AExtension.dll and BExtension.dll without any problems due to them referencing two assemblies that only differ by their publicKeyToken?
Does the order in which the extensions are loaded make a difference?
Does the answer change if CoolProgram.exe does not have a strong name, but both AExtension.dll and BExtension.dll do have strong names?
The same as question 1, but applied to situation 5.2.
Optional Background Information:
If two assemblies are compatible at runtime; i.e. they expose the same public API and only differ in their implementation (e.g. one restricted to .NET 3.5 for the implementation and one using .NET 4.0 types in the private implementation code), then users will not face assembly binding problems in extensible applications even if the two assemblies have exactly the same strong name. This is not the case for situations where the public API differs in some way.
One solution to the case where the public API differs is to use separate names for each version of an assembly. This could lead to cases like the following for the ANTLR 4 Runtime:
Antlr4.Runtime.net20.dll
Antlr4.Runtime.net30.dll
Antlr4.Runtime.net35.dll
Antlr4.Runtime.net40.dll
Antlr4.Runtime.net45.dll
Antlr4.Runtime.portable_net40.dll
Antlr4.Runtime.portable_net45.dll
Antlr4.Runtime.netcore45.dll
The documentation associated with the project could be simplified if all the assemblies could be named Antlr4.Runtime.dll. In the case where users know they are working in an environment where multiple vendors could be providing code that references assemblies with different target frameworks but otherwise the same version, steps could be taken to ensure their assemblies can be located at runtime. A concrete example would be two Visual Studio extensions using ANTLR for syntax highlighting, one targeting Visual Studio 2010+ (using .NET 4.0), and one targeting Visual Studio 2012+ (using .NET 4.5). The [ProvideBindingPath] and/or [ProvideCodeBase] attribute could be used to provide exactly the functionality described in situation 5.2.

Related

You must add a reference to assembly 'Microsoft.Data.Services.Client.Portable...' & NUGET

I have created a VS2013 solution that contains multiple projects. One of those projects is a portable class library targeting .NET 4.5+, Silverlight 5, Windows Store 8+ and Windows Phone 8 and this project contains a reference to an OData service in an accompanying web application.
The portable class library references Microsoft.Data.Services.Client.Portable (among others), added via nuget (WCF Data Services Client).
I have then added the portable class library to a WPF (.NET 4.5) application, a Windows Store application and a Windows Phone application and written some very basic test code to access the service. This works fine in Windows Store and Windows Phone.
The WPF application however will not compile. The errors are...
The type 'System.Data.Services.Client.DataServiceContext' is defined
in an assembly that is not referenced. You must add a reference to
assembly 'Microsoft.Data.Services.Client.Portable, Version=5.6.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
The type 'System.Data.Services.Client.DataServiceQuery`1' is defined in an
assembly that is not referenced. You must add a reference to assembly
'Microsoft.Data.Services.Client.Portable, Version=5.6.0.0,
Culture=neutral, PublicKeyToken=31bf3856ad364e35'.
The thing is, I also added the WCF Data Services Client to the WPF application via nuget, but it does not add a reference to the portable library (packages\Microsoft.Data.Services.Client.5.6.0\lib\portable-net45+sl5+wp8+win8\Microsoft.Data.Services.Client.Portable.dll), instead adding a reference to the full framework 4.0 version (packages\Microsoft.Data.Services.Client.5.6.0\lib\net40\Microsoft.Data.Services.Client.dll) - which in turn is causing the error I am seeing.
Is there something I am doing wrong here or is this an error in the installation package? Note that if I delete the offending reference and add the alternative reference manually then all is well so though I have a work-around I would still like to know if I am the cause of the error.
Looking at the NuGet source code this behaviour seems to be by design.
The WCF Data Services Client contains assemblies for the following frameworks:
.NET Framework, v4.0
.NET Portable, net45, sl5, wp8, win8
Silverlight, v4.0
Installing this NuGet package into a project that targets .NET 4.5 will result in the .NET 4.0 assembly from the NuGet package being referenced. NuGet considers the more specific .NET framework to be a better match for your WPF project which targets .NET 4.5.
There is a comment in the NuGet source code about this when it looks for the best matching assembly in the NuGet package.
// Let's say a package has two framework folders: 'net40' and 'portable-net45+wp8'.
// The package is installed into a net45 project. We want to pick the 'net40' folder, even though
// the 'net45' in portable folder has a matching version with the project's framework.

Adding multiple versions of WinForms control in Visual Studio Toolbox

I have multiple DLLs of a WinForms control targeted for different versions of .NET Framework and need to add them all in a Visual Studio Toolbox while showing only the one which is most suitable for currently selected version of .NET.
The control have different features when compiled against different versions of .NET, this is why it would be best to show the most "native" version only. For example, the control have some features removed in .NET 4.0 Client Profile or makes use of .NET 3.0 features when available (not avaiable in .NET 2.0).
The problem is that the control have same name and is signed with same Strong Name Key (SNK).
I can modify source code, but what to do to enable all versions of the component to reside in VS Toolbox?

XAML namespaces: winfx vs netfx

When looking at the documentation for WPF (e.g. for Selector.SelectedItem), I noticed that there are two XML naspaces: http://schemas.microsoft.com/winfx/2006/xaml/presentation and http://schemas.microsoft.com/netfx/2007/xaml/presentation.
What's the difference between the two, if any? Why are there two different namespaces that seem to point to the same group of .Net namespaces (do they really?)?
(guessing the answer)
the first version of WPF was called WinFX and was probably a separated project in MS organisation.
When WinFX joined the .Net Framework, MS has probably wished to keep the namespaces defines earlier for compatibility with existing work.
Later, new classes have been added, and MS decided to use a properly named namespace (NetFX is .Net Framework).

Sorrow with Data Transfer Objects in Silverlight / WCF

I have a Silverlight app hosted in an Azure web role ASP project. The ASP project exposes a WCF service.
I would like to have one set of class definitions for the data types. Someone recommended making a third project (class library) and adding a reference to it from the SL and ASP. I started doing this, but the Silverlight project complained that you can only add references to Silverlight projects.
I then made a Silverlight class library and moved the data classes to it. However, I to add some .dll references, like to the Windows Azure storage client. Then the Silverlight class library tells me I can only add references to Silverlight 4-friendly .dlls, of which Windows Azure isn't one. Fantastic.
Is there something I can do to get around this, or am I stuck with a less elegant, redundant solution?
Multi-targeting is your best bet. There is an article explaining this in Visual Studio from Microsoft at:
http://msdn.microsoft.com/en-us/library/ff921092(PandP.20).aspx
Basically, you create both your Silverlight and standard .NET class libraries, each with a different name, and then include the same files into each. Usually the files are actually only in one of the class libraries and then soft linked in the second one.
The key is to ensure that the code in your files is compatible with both runtimes. If there needs to be separate implementation for some of your methods depending on the runtime then you need to separate these with pragmas (i.e. #ifdef SILVERLIGHT...).
If you're only doing data structures, however, there should be no issues as long as Silverlight supports the objects you are using.
See if using linked files as per this answer does the trick for you.

Sharing assemblies between .Net 4 and Silverlight 4

At the last PDC (can't remember which talk it was) they gave us the information that it will be possible to share assemblies between regular .Net 4 and Silverlight 4.
Unfortunately I can't find anything on this. Was this feature dropped? What options/limitations are there?
(There are similar questions on SO but they don't say if they apply to SL3 or 4.)
See Sharing Silverlight Assemblies with .NET Apps from the CLR Team Blog.
Basically if your assembly only references:-
Mscorlib
System
System.Core
System.ComponentModel.Composition
Microsoft.VisualBasic
That assembly can be shared by both frameworks with each framework using its own version of those references (that is .NET won't be attempting to load Silverlight's version of System.Core for instance).
Of course you will still need to limit your code to features of these references that are actually common across to the two frameworks.

Resources