Chapter 18 - Assemblies
FolderBasedALC
void Main() { FolderBasedALC alc = new FolderBasedALC (@"C:\YourAssemblyFolder"); alc.LoadFromAssemblyName (new AssemblyName ("YourAssembly")); foreach (Assembly a in alc.Assemblies) Console.WriteLine (a.FullName); } class FolderBasedALC : AssemblyLoadContext { readonly string _folder; public FolderBasedALC (string folder) => _folder = folder; protected override Assembly Load (AssemblyName assemblyName) { // Attempt to find the assembly: string targetPath = Path.Combine (_folder, assemblyName.Name + ".dll"); if (File.Exists (targetPath)) return LoadFromAssemblyPath (targetPath); // Load the assembly return null; // We can’t find it – it could be a framework assembly } }
AssemblyDependencyResolver
var resolver = new AssemblyDependencyResolver (@"c:\PathToSomeAssemblyWithDepsDotJson.dll"); string path = resolver.ResolveAssemblyToPath (new AssemblyName ("someDependentAssembly"));
Writing a Plug-in System - Plugin.Common
namespace Plugin.Common { public interface ITextPlugin { string TransformText (string input); } }
Writing a Plug-in System - Capitalizer
public class CapitalizerPlugin : Plugin.Common.ITextPlugin { public string TransformText (string input) => input.ToUpper(); }
Writing a Plug-in System - Host
class PluginLoadContext : AssemblyLoadContext { AssemblyDependencyResolver _resolver; public PluginLoadContext (string pluginPath, bool collectible) // Give it a friendly name to help with debugging: : base (name: Path.GetFileName (pluginPath), collectible) { // Create a resolver to help us find dependencies. _resolver = new AssemblyDependencyResolver (pluginPath); } protected override Assembly Load (AssemblyName assemblyName) { // See below if (assemblyName.Name == typeof (ITextPlugin).Assembly.GetName().Name) return null; string target = _resolver.ResolveAssemblyToPath (assemblyName); if (target != null) return LoadFromAssemblyPath (target); // Could be a framework assembly. Allow the default context to resolve. return null; } protected override IntPtr LoadUnmanagedDll (string unmanagedDllName) { string path = _resolver.ResolveUnmanagedDllToPath (unmanagedDllName); return path == null ? IntPtr.Zero : LoadUnmanagedDllFromPath (path); } } class Program { const bool UseCollectibleContexts = true; static void Main() { const string captializer = @"C:\source\PluginDemo\" + @"Capitalizer\bin\Debug\netcoreapp3.0\Capitalizer.dll"; Console.WriteLine (TransformText ("big apple", captializer)); } static string TransformText (string text, string pluginPath) { var alc = new PluginLoadContext (pluginPath, UseCollectibleContexts); try { Assembly assem = alc.LoadFromAssemblyPath (pluginPath); // Locate the type in the assembly that implements ITextPlugin: Type pluginType = assem.ExportedTypes.Single (t => typeof (ITextPlugin).IsAssignableFrom (t)); // Instantiate the ITextPlugin implementation: var plugin = (ITextPlugin)Activator.CreateInstance (pluginType); // Call the TransformText method return plugin.TransformText (text); } finally { if (UseCollectibleContexts) alc.Unload(); // unload the ALC } } }