I am now creating a new small version of the project. This project is released on NuGet and is compatible with .NET 4.0 and higher. Some of the new features that I present require .NET 4.5 (users should be able to IReadOnlyCollection<T> and IReadOnlyList<T> , both of the interfaces that were introduced in .NET 4.5), but I need the project to be compatible with. NET 4.0, as not all developers can easily upgrade to the latest .NET platform.
So, Im problem is faced with how to solve this "direct compatibility" problem. There are two solutions that I thought of, but both of them are not very attractive, so hopefully someone can give me some ideas or recommendations here.
Here are two solutions I came up with:
Solution 1. Use the #if compiler #if and create a version of the DLL for the .NET platform and send these versions using the NuGet packages and upload them to the project site.
The disadvantage of this method is that when developers upgrade their Visual Studio project from .NET 4.0 to .NET 4.5, they do not automatically receive .NET 4.5 (with specific .NET 4.5 features). This violates the Least of Surprise Principle and leaves developers stunned at why the feature doesn't work when they try to use it a few months later.
Solution 2. Use one single DLL and type emot on the fly, which implement both new interfaces when they exist in the current application domain. This allows you to send a single DLL to the user and allows available functions when the developer switches the .NET framework versions to his project. This will make things "just work." This is the direction Im currently heading btw.
Since I need to return a type that should implement interfaces, the disadvantage is that this type must be created at runtime using Reflection.Emit, ModuleBuilder, TypeBuilder, etc. This is seriously nasty. But in addition, since this type must be created in a new (anonymous) assembly, I have to make some internal types public (the type that needs to be inherited, and the interface that needs to be implemented). If these internal types publicly pollute the project API and will not allow me to make changes to these types.
I think these are my options, but I could have missed something obvious. So my question is: am I missing an opportunity? Is there a way around workarounds for solution 1, or would it be better to go with a hardcore root from a runtime type?