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
}
}
}