Using different versions of DLLs causes Blish crashes
Taschenbuch opened this issue · 0 comments
Taschenbuch commented
Problem
- blish modules and blish core can reference different versions of the same dependency. A dependency can be a nuget or just a simple dll. This can lead to crashes because only one version of the dependency will be loaded by .NET.
- example: Module A uses a nuget in version 1, Module B uses the same nuget but in version 2. This will cause crashes when Module A or B uses methods or other features of the nuget that changed between the versions 1 and 2. e.g. new methods, removed methods. methods with changed signature (return value changed, parameter types or number of parameters changed).
- More explicit example: nugetV1 has the method .CreateLabelName(string name), but nugetV2 changed this method to .CreateLabelName(string name, string namePrefix). When nugetV2 is loaded, the call nugetV1.CreateLabelName(string name) will crash blish. When nugetV1 is loaded instead, the call nugetV2.CreateLabelName(string name, string namePrefix) will crash blish.
- Typically the exception thrown in this case says something about "Not found"
- examples where this can or already has happened in Blish:
- Newtonsoft.JSON: many modules use this. It did not cause issues yet, because this nuget is rarely updated. So every module uses almost the same version.
- lite.db: caused blish crashs because modules used different versions (e.g. Minstril Module and MistQuil Module)
- when someone makes a custom nuget and uses it it multiple modules. And then updates this nuget to a newer version and use the updated nuget in new module versions. e.g. Blish-Extended:
- when someone creates an additional assembly which he uses in multiple module projects.
- discussions about this issue
NOT a solution
- when multiple old modules use the same nuget version, just update all modules to the newer nuget version and release them.
- This will not work reliable, because users will not always update all modules to the newest version
- even while updating the modules step by step there will be modules enabled in different versions during the update process.
- the modules are in control by different module developers which may already have become inactive. So it is unlikely that it can be easily coordinated to create new releases for all modules involved at the same time.
possible solutions
shared projects
- a special project type where the code of the project is "inlined" into other projects.
- https://learn.microsoft.com/en-us/xamarin/cross-platform/app-fundamentals/shared-projects?tabs=macos
- used by estreya now (?).
- start of longer discussion on this on discord:
https://discord.com/channels/531175899588984842/599270434642460753/1069340391985397911
Strong-named assemblies
- did not work when estreya tested it https://discord.com/channels/531175899588984842/536970543736291346/1011620581805924444
- and later used in mistwars module which caused blish crashs for many users
- One problem seems to be that when you use one Strong-named assembly, every assembly referenced in this Strong-named assembly has to be Strong-named too, which is usually not the case and is a lot of work / too much work.
app domains
- mentioned by denrage
bindingRedirect
- probably will not solve problem with regular third party dependency.
- may work for managing a self created dependency. But only when new versions of the dependency are fully backwards compatible. e.g. old method signatures are not changed. only new methods are added.
workaround: use git subrepots instead of .dll/nuget dependency
- place the common code files into a git subrepo. add the common code git subrepo code files directly into each module project as if they are part of those module projects (the files, not a common project as a project reference! we dont want to create a new dll).
- discussion: https://discord.com/channels/531175899588984842/536970543736291346/1016054659670081606