diff --git a/README.md b/README.md index 0fa5d57..e2bd9dd 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -.NET Core Plugins -================= +.NET Plugins +============ [![Build Status][ci-badge]][ci] [![Code Coverage][codecov-badge]][codecov] [![NuGet][nuget-badge] ![NuGet Downloads][nuget-download-badge]][nuget] @@ -13,10 +13,13 @@ [nuget-download-badge]: https://img.shields.io/nuget/dt/McMaster.NETCore.Plugins?style=flat-square -This project provides API for loading .NET Core assemblies dynamically, executing them as extensions to the main application, and finding and **isolating** the dependencies of the plugin from the main application. -This library supports .NET Core 2, but works best in .NET Core 3 and up. It allows fine-grained control over +This project provides API for loading .NET assemblies dynamically, executing them as extensions to the main application, and finding and **isolating** the dependencies of the plugin from the main application. It allows fine-grained control over assembly isolation and type sharing. Read [more details about type sharing below](#shared-types). +> **Note** +> +> 2.0+ of library supports .NET 6. If you still need .NET < 6 support, look for an old 1.* version of this library. + Blog post introducing this project, July 25, 2018: [.NET Core Plugins: Introducing an API for loading .dll files (and their dependencies) as 'plugins'](https://natemcmaster.com/blog/2018/07/25/netcore-plugins/). **Since 2018, .NET Core 3** @@ -43,7 +46,7 @@ PluginLoader.CreateFromAssemblyFile( * assemblyFile = the file path to the main .dll of the plugin * sharedTypes = a list of types which the loader should ensure are unified. (See [What is a shared type?](#shared-types)) -* isUnloadable = (.NET Core 3+ only). Allow this plugin to be unloaded from memory at some point in the future. (Requires ensuring that you have cleaned up all usages of types from the plugin before unloading actually happens.) +* isUnloadable = Allow this plugin to be unloaded from memory at some point in the future. (Requires ensuring that you have cleaned up all usages of types from the plugin before unloading actually happens.) See example projects in [samples/](./samples/) for more detailed, example usage. @@ -70,7 +73,9 @@ There is nothing special about the name "IPlugin" or the fact that it's an inter ### The plugins -Typically, it is best to implement plugins by targeting `net5.0` or higher. They can target `netstandard2.0` as well, but using `net5.0` is better because it reduces the number of redundant System.\* assemblies in the plugin output. +> **Warning** +> +> Using `netstandard2.0` as the TargetFramework for your plugin project has known issues. Use `net6.0` instead. A minimal implementation of the plugin could be as simple as this. @@ -159,7 +164,7 @@ Shared types allow you define the kinds of objects that will be passed between p For example, let's say you have a simple host app like [samples/hello-world/](./samples/hello-world/), and two plugins which were compiled with a reference `interface IPlugin`. This interface comes from `Contracts.dll`. When the application runs, by default, each plugin and the host will have their own version of `Contracts.dll` -which .NET Core will keep isolated. +which .NET will keep isolated. The problem with this isolation is that an object of `IPlugin` created within the "PluginApple" or "PluginBanana" context does not appear to be an instance of `IPlugin` in any of the other plugin contexts. @@ -205,7 +210,7 @@ See example projects in [samples/aspnetcore-mvc/](./samples/aspnetcore-mvc/) for Sometimes you may want to use a plugin along with reflection APIs such as `Type.GetType(string typeName)` or `Assembly.Load(string assemblyString)`. Depending on where these APIs are used, they might fail to -load the assemblies in your plugin. In .NET Core 3+, there is an API which you can use to set the _ambient context_ +load the assemblies in your plugin. There is an API which you can use to set the _ambient context_ which .NET's reflection APIs will use to load the correct assemblies from your plugin. Example: @@ -224,7 +229,7 @@ Read [this post written by .NET Core engineers](https://github.com/dotnet/corecl ## Overriding the Default Load Context -Under the hood, DotNetCorePlugins is using a .NET Core API called [ApplicationLoadContext][alc-api]. +Under the hood, DotNetCorePlugins is using a .NET API called [ApplicationLoadContext][alc-api]. This creates a scope for resolving assemblies. By default, `PluginLoader` will create a new context and fallback to a **default context** if it cannot find an assembly or if type sharing is enabled. The default fallback context is inferred when `PluginLoader` is instantiated. In certain advanced scenarios, diff --git a/samples/aspnetcore-mvc/README.md b/samples/aspnetcore-mvc/README.md index 949325a..123bd75 100644 --- a/samples/aspnetcore-mvc/README.md +++ b/samples/aspnetcore-mvc/README.md @@ -17,7 +17,7 @@ Open a command line to this folder and run: ``` dotnet restore -dotnet run -p MvcApp/ +dotnet run --project MvcApp/ ``` Then open diff --git a/samples/dependency-injection/README.md b/samples/dependency-injection/README.md index 99a44cf..bef3b56 100644 --- a/samples/dependency-injection/README.md +++ b/samples/dependency-injection/README.md @@ -14,5 +14,5 @@ Open a command line to this folder and run: ``` dotnet restore -dotnet run -p DI.HostApp/ +dotnet run --project DI.HostApp/ ``` diff --git a/samples/dynamic-implementation/README.md b/samples/dynamic-implementation/README.md index 0640a76..a3a2a14 100644 --- a/samples/dynamic-implementation/README.md +++ b/samples/dynamic-implementation/README.md @@ -17,5 +17,5 @@ Open a command line to this folder and run, otherwise open the .sln file: ``` dotnet restore -dotnet run -p Host/ +dotnet run --project Host/ ``` diff --git a/samples/hello-world/README.md b/samples/hello-world/README.md index 0f5a42d..c8a8820 100644 --- a/samples/hello-world/README.md +++ b/samples/hello-world/README.md @@ -13,5 +13,5 @@ Open a command line to this folder and run: ``` dotnet restore -dotnet run -p HostApp/ +dotnet run --project HostApp/ ``` diff --git a/samples/hot-reload/run.ps1 b/samples/hot-reload/run.ps1 old mode 100644 new mode 100755 index 4916ba0..bdd2dc9 --- a/samples/hot-reload/run.ps1 +++ b/samples/hot-reload/run.ps1 @@ -1,3 +1,5 @@ +#!/usr/bin/env pwsh + $ErrorActionPreference = 'Stop' Push-Location $PSScriptRoot diff --git a/samples/hot-reload/run.sh b/samples/hot-reload/run.sh index 254b8ed..e991b47 100755 --- a/samples/hot-reload/run.sh +++ b/samples/hot-reload/run.sh @@ -23,7 +23,7 @@ trap "kill 0" EXIT echo -e "${YELLOW}run.sh:${RESET} Use CTRL+C to exit" -dotnet run --no-build -p HotReloadApp -- "$publish_dir/TimestampedPlugin.dll" & +dotnet run --no-build --project HotReloadApp -- "$publish_dir/TimestampedPlugin.dll" & while true do diff --git a/src/Plugins.Mvc/releasenotes.props b/src/Plugins.Mvc/releasenotes.props index e0032bf..4cb63cb 100644 --- a/src/Plugins.Mvc/releasenotes.props +++ b/src/Plugins.Mvc/releasenotes.props @@ -1,5 +1,10 @@  + +Breaking change: require .NET 6+ + +See also https://nuget.org/packages/McMaster.NETCore.Plugins/$(VersionPrefix) for its release notes. + No changes to this library, but updated to use 1.1.0 of Microsoft.NETCore.Plugins. See https://nuget.org/packages/McMaster.NETCore.Plugins/$(VersionPrefix) for its release notes. diff --git a/src/Plugins/releasenotes.props b/src/Plugins/releasenotes.props index e772487..bce3b22 100644 --- a/src/Plugins/releasenotes.props +++ b/src/Plugins/releasenotes.props @@ -1,5 +1,10 @@  + +Breaking changes: +* Require .NET 6 +. Drop support for .NET Core 2, 3, and 5. +* Drop dependencies on .NET Core 2 libraries for manually parsing .deps.json. Use the built-in .NET 6 API for this. + Changes: * @Sewer56 - feature: add option to support lazy loading of transitive dependencies to increase performance (PR #164)