Extension loading mechanism
Overview
Different versions of libraries can be used per extension
Next Design loads libraries in different areas per extension. This allows different versions of the same library to be used by each extension.
Objective
- Extensions allow multiple extensions to use different versions of the same library.
Extension A uses version 4.7.1
of System.Text.Json
, and another extension B can use the new version 5.0.2
of System.Text.Json
. In this case, extension A uses version 4.7.1
of the API, and extension B uses version 5.0.2
of the API.
- Extensions can use newer versions of libraries than the libraries referenced by the Next Design main body.
Extensions can use newer versions of libraries than the Microsoft.WindowsAPICodePack
referenced by the Next Design main body.
If the version of the library referenced by the extension is lower than the version of the library included in the Next Design main body, the corresponding library on the extension side will not be loaded, and the library already loaded on the Next Design main body side will be used.
This is for the following reasons.
- Reduce the memory size reserved for the library loading area
- Guarantee the operation of the Next Design main body side
- Reduce interface inconsistencies caused by data exchange between the Next Design main body and the extension
How to resolve extension dependent libraries
Next Design uses the assembly metadata description file (*.deps.json file) to resolve the location of the extension's dependent libraries.
In addition, it can correctly recognize dependent libraries even if they are native libraries.
Objectives
- The deployment configuration of dependent libraries can be customized on the extension side by describing assembly metadata.
- If dependent libraries are resolved using the NuGet package management function, the assembly metadata description file (*.deps.json file) is automatically generated at build time.
- Therefore, it is recommended that extensions use the NuGet package management function to resolve dependent libraries.
- Extensions that depend on native libraries can be distributed.
- Extensions that depend on native libraries can be deployed by using the assembly metadata description file (*.deps.json file).
- Even if the dependent native libraries are different due to differences in OS or CPU, the issue is resolved when the extension is executed, so for example, native libraries for
win-x64
andwin-x86
can be included in one extension.
Handling static variables in libraries referenced by multiple extensions
In Next Design, libraries are loaded into different areas for each extension. Accordingly, static variables are handled as follows.
- Since memory management is different for each extension, static variables (such as class variables) are not shared between multiple extensions.
- Therefore, static variables cannot be used to share information between extensions.
For example, even if you define the following class variable in one extension, the value of _SomeDictionary cannot be referenced from another extension.
public class SomeClass
{
private static IDictionary<string, object> _SomeDictionary = new Dictionary<string, object>();
}
About shared libraries
Overview of shared libraries
In Next Design, libraries are loaded into different areas for each extension so that extensions can use newer versions of libraries than those referenced by Next Design itself. However, depending on the library, loading it into a different area may affect operation. Shared libraries are a mechanism to load such libraries into the same area to avoid affecting operation.
- If a library referenced by an extension is specified as a shared library, it will be shared with other extensions. This allows objects managed by other extensions to be passed.
- If different versions of a library are specified as a shared library for each extension, the newest version of the library will be loaded and shared. This allows functional improvements and bug fixes to be applied automatically.
If you want to use a newer version of a library than the one included with Next Design in your extension, do not specify that library as a shared library.
Loading a shared library
Next Design scans the manifests of all active extensions1 regardless of their lifecycles to determine which libraries are specified as shared libraries. At this time, if different versions of the same library are specified as shared libraries in each extension, the library with the latest file version among those libraries will be loaded.
With this mechanism, even if an extension has an older version of a library, it will use the latest library placed in another extension folder.
In addition, for cultures (resources), resource libraries are loaded for the culture of the Next Design main body2. At this time, subfolders such as ja
and en
in the same folder as the library to be loaded as a shared library are searched.
- The shared libraries of an extension are searched for in the folders below the extension's execution folder.
However, folders (and their subfolders) that meet the following conditions will be excluded from the search. - Folders whose names start with "."
- Folders that contain executable files (*.exe)
Restrictions on shared libraries
- Native libraries cannot be specified as shared libraries. Configure shared libraries so that they do not include native libraries.
- Libraries referenced by Next Design itself cannot be specified as shared libraries. Define the manifest so that libraries referenced by Next Design itself are not specified as shared libraries.
Notes on shared libraries
If there are extensions that specify the same library as a shared library and extensions that do not specify it as a shared library, the shared library will be used by all extensions.
This mechanism allows bug fixes and the latest features to be used even for extensions that have older versions of libraries.
However, if the library in question does not guarantee backward compatibility, runtime errors may occur in the extension.
If a library referenced by an extension is not specified as a shared library, it will be loaded as a non-shared library. If a library is specified as a shared library, that library, as well as all libraries referenced by that library, will be loaded as shared libraries.
And if a non-shared library and a shared library reference the same library, the same library will be loaded twice under separate memory management.
In this state, even if the same type is defined in the same library, runtime errors may occur such as not being found under the memory management of the other.
For extensions that reference such libraries, including extensions that use WPF, specify all applicable libraries as shared libraries.
Notes on extension development and maintenance
If the library referenced by an extension is a non-shared library, the version of the library referenced when the extension is executed is determined according to the following rules.
Extension included (A) | Next Design included (B) | Old or new library version | Referenced version |
---|---|---|---|
Included | - | - | (A) |
- | Included | - | (B) |
Included | Included | (A) is newer than (B) | (A) |
Included | Included | (A) and (B) are the same, or (B) is newer than (A) | (B) |
For shared libraries between extensions, the newest version of the library included with each extension is referenced.
Also, libraries included with Next Design cannot be specified as shared libraries.
Please understand the above rules and pay attention to the following points when developing and maintaining extensions.
During development, make sure that the extension works correctly when combined with the target version of Next Design and other extensions that reference the shared library.
During maintenance, check the version of the library referenced when the extension is executed according to the following changes, and make sure that the extension works correctly when combined with that version.
- The Next Design main body has been upgraded and the libraries included with it and their versions have changed.
- The shared library specification has been changed in other extensions.
- The version of the library specified as the shared library in other extensions has been changed.
Extension distribution procedure and precautions
When distributing an extension, configure the files to be distributed according to the following.
Extension Folder Structure
In Next Design, in addition to the manifest file, extension main library, and dependent libraries, an assembly metadata description file (*.deps.json file) is placed in the extension distribution folder.
{Extension folder}/
manifest.json
{Extension main library name}.dll
{Extension main library name}.deps.json
{Extension dependent library name}.dll
・・・
Assembly metadata description file
When you build an extension with dotnet build, it is automatically created in the output folder of the build result. For details, see below.
- When distributing an extension, place the generated
*.deps.json file
in the extension folder. - If they are not deployed, the extension may fail to load the libraries it depends on.
Collecting dependent libraries
You can collect the dependent libraries of an extension to the output folder with dotnet publish. For details, see below.
- dotnet publish collects all dependent libraries.
- If an extension uses a library that also references the Next Design main body, if the library is not a newer version than the main body, you can remove it from the package when distributing the extension to reduce the package size.
Deploying internationalization resource DLLs
DLL-based extensions can use standard C# localization.
- If the extension (and its dependent libraries) are internationalized using string resources, a library (*.resources.dll) containing resource information by language will be generated in the output folder.
- When distributing the extension, place these libraries in the extension folder along with the folder structure.
{Extension folder}/
en/
{Extension main library name}.resources.dll
fr/
{Extension main library name}.resources.dll
manifest.json
{Extension main library name}.dll
{Extension main library name}.deps.json
{Extension dependent library name}.dll
...
Placing native libraries
Next Design allows you to use native libraries in extensions.
- If the extension (and its dependent libraries) depend on native libraries, native libraries for each runtime environment will be output to the output folder.
- When distributing an extension, place these libraries in the extension folder along with the folder structure.
{Extension folder}/
runtimes/
win-x64/
{Native library name}.dll
win-x86/
{Native library name}.dll
manifest.json
{Extension main library name}.dll
{Extension main library name}.deps.json
{Extension dependent library name}.dll
...
Restrictions
Conflict with libraries referenced by Next Design main body
Libraries of older versions than the libraries referenced by Next Design main body will not be loaded. The newer version of the library referenced by the main body will be used. Therefore, when an extension uses an older version of a library that is the same as a library in the same folder as the Next Design exe, if backward compatibility is not guaranteed between those libraries, the extension will fail to activate or an error will occur when it is executed.
- For example, if an extension built with an old
Next Design.Core
references an interface that is deprecated in the newNext Design.Core
, an error will occur because the new Next Design cannot resolve the interface.
Restrictions on extensions that reference native libraries
Due to .NET restrictions, it may not be possible to resolve the location of a native library.
- If a native library is requested to be loaded by NativeLibrary.Load(), the extension load mechanism cannot resolve it.
- Therefore, if the native library is loaded with the above method, the library must be located in a location that can be loaded by NativeLibrary.Load().
Currently known native libraries that fall under the above restrictions
- This applies to the SQLite native library (e_sqlite3.dll) used in EFCore.
- Next Design includes native libraries for EFCore 3.1 to ease the above restrictions.
- Therefore, the operation of extensions that depend on versions other than EFCore 3.1 is not guaranteed.
Restrictions on temporary assembly file generation
If an extension uses a function that requires the generation of temporary assembly files at runtime, the extension load mechanism may not be able to identify the storage location of those assembly files, and the extension may not work properly. Follow the information from the developer of the function you use and select an implementation method that avoids the generation of temporary assembly files.