Gorgon
Show / Hide Table of Contents

Class GorgonMefPlugInCache

A cache to hold MEF plugin assemblies.

Inheritance
object
GorgonMefPlugInCache
Implements
IDisposable
Inherited Members
object.ToString()
object.Equals(object)
object.Equals(object, object)
object.ReferenceEquals(object, object)
object.GetHashCode()
object.GetType()
Namespace: Gorgon.PlugIns
Assembly: Gorgon.Core.dll
Syntax
public sealed class GorgonMefPlugInCache : IDisposable
Remarks

This assembly cache is meant to load/hold a list of plugin assemblies that contain types that implement the GorgonPlugIn type and is meant to be used in conjunction with the IGorgonPlugInService type.

The cache attempts to ensure that the application only loads an assembly once during the lifetime of the application in order to cut down on overhead and potential errors that can come up when multiple assemblies with the same qualified name are loaded into the same context.

Examples

This example shows how to load a plugin and get its plugin instance. It will use the ConcreteFunctionalityPlugIn above:

// Our base functionality.
private FunctionalityBase _functionality;
private GorgonMefPlugInCache _assemblies;

void LoadFunctionality()
{
	assemblies = new GorgonMefPlugInCache();

	// For brevity, we've omitted checking to see if the assembly is valid and such.
	// In the real world, you should always determine whether the assembly can be loaded 
	// before calling the Load method.
	_assemblies.LoadPlugInAssemblies(@"Your\Directory\Here", "file search pattern");  // You can pass a wild card like *.dll, *.exe, etc..., or an absolute file name like "MyPlugin.dll".

	IGorgonPlugInService pluginService = new GorgonMefPlugInService(_assemblies);

	_functionality = pluginService.GetPlugIn<FunctionalityBase>("Fully.Qualified.Name.ConcreteFunctionalityPlugIn"); 
}

void Main()
{
	LoadFunctionality();

	Console.WriteLine($"The ultimate answer and stuff: {_functionality.DoSomething()}");

    _assemblies?.Dispose();
}

Constructors

| Edit this page View Source

GorgonMefPlugInCache(IGorgonLog)

Initializes a new instance of the GorgonMefPlugInCache class.

Declaration
public GorgonMefPlugInCache(IGorgonLog log = null)
Parameters
Type Name Description
IGorgonLog log

[Optional] The application log file to use.

Properties

| Edit this page View Source

PlugInAssemblies

Property to return the list of cached plugin assemblies.

Declaration
public IReadOnlyList<string> PlugInAssemblies { get; }
Property Value
Type Description
IReadOnlyList<string>

Methods

| Edit this page View Source

Dispose()

Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.

Declaration
public void Dispose()
Remarks

important

This method must be called, or the application domain that is created to interrogate assembly types will live until the end of the application. This could lead to memory bloat or worse.

Because the application domain is unloaded on a separate thread, it may deadlock with the finalizer thread and thus we cannot count on the finalizer to clean evict the stale app domain on our behalf.

| Edit this page View Source

EnumeratePlugIns()

Function to enumerate all the plugin names from the assemblies loaded into the cache.

Declaration
public IEnumerable<Lazy<GorgonPlugIn, IDictionary<string, object>>> EnumeratePlugIns()
Returns
Type Description
IEnumerable<Lazy<GorgonPlugIn, IDictionary<string, object>>>

A composition container containing the plugins from the assemblies.

| Edit this page View Source

IsManagedAssembly(string)

Function to determine if the assembly defined in the assembly path is a .NET managed assembly or not.

Declaration
public static (bool isManaged, AssemblyPlatformType platform) IsManagedAssembly(string assemblyPath)
Parameters
Type Name Description
string assemblyPath

The path to the assembly.

Returns
Type Description
(bool isManaged, AssemblyPlatformType platform)

A tuple containing true if the file is a .NET managed assembly, false if not, and the type of expected platform that the assembly code is supposed to work under.

| Edit this page View Source

LoadPlugInAssemblies(string, string)

Function to load any DLL assemblies in the specified directory path.

Declaration
public void LoadPlugInAssemblies(string directoryPath, string filePattern = "*.dll")
Parameters
Type Name Description
string directoryPath

The path containing the plug in DLLs to load.

string filePattern

[Optional] The file pattern to search for.

Remarks

If the filePattern is specified, then a standard file search wildcard can be used to located specific files to load (e.g. MyPlugIn-*.dll, OtherTypes*.so, etc...).

Exceptions
Type Condition
ArgumentNullException

Thrown when the directoryPath parameter is null.

ArgumentEmptyException

Thrown when the directoryPath parameter is empty.

DirectoryNotFoundException

Thrown if the directory specified by directoryPath does not exist.

| Edit this page View Source

Refresh()

Function to refresh the loaded plugin assembly list, and import any other assemblies that match the previously watched paths.

Declaration
public void Refresh()
| Edit this page View Source

VerifyAssemblyStrongName(string, byte[])

Function to determine if an assembly is signed with a strong name key pair.

Declaration
public static AssemblySigningResults VerifyAssemblyStrongName(string assemblyPath, byte[] publicKey = null)
Parameters
Type Name Description
string assemblyPath

Path to the assembly to check.

byte[] publicKey

[Optional] The full public key to verify against.

Returns
Type Description
AssemblySigningResults

A value from the AssemblySigningResults.

Remarks

This method can be used to determine if an assembly has a strong name key pair (i.e. signed with a strong name) before loading it. If the assembly is not found, then the result of this method is NotSigned.

The publicKey parameter is used to compare a known full public key (note: NOT the token) against that of the assembly being queried. If the bytes in the public key do not match that of the public key in the assembly being queried, then the return result will have a KeyMismatch value OR'd with the result. To check for a mismatch do the following:

// Compare the key for the current assembly to that of another assembly.
byte[] expected = this.GetType().Assembly.GetName().GetPublicKey();

AssemblySigningResult result = assemblyCache.VerifyAssemblyStrongName("Path to your assembly", expected);

if ((result & AssemblySigningResult.KeyMismatch) == AssemblySigningResult.KeyMismatch) { Console.Writeline("Public token mismatch."); }

important

Disclaimer time!!!

If the security of your assemblies is not critical, then this method should serve the purpose of verification of an assembly. However:

This method is intended to verify that an assembly is signed, optionally contains the provide public key, and that, to the best of its knowledge, it has not been tampered with. This is not meant to protect a system against malicious code, or provide a means of checking an identify for an assembly. This method also makes no guarantees that the information is 100% accurate, so if security is of the utmost importance, do not rely on this method alone and use other functionality to secure your assemblies.

For more information about signing an assembly, follow this link Creating and Using Strong-Named Assemblies.

Implements

IDisposable

Extension Methods

GorgonDebugExtensions.ValidateObject<T>(T, string)
EditorPlugInExtensions.ValidateAndLoadAssemblies(GorgonMefPlugInCache, IEnumerable<string>, IGorgonLog)
GorgonNullExtensions.AsNullable<T>(object)
GorgonNullExtensions.IfNull<T>(object, T)
GorgonNullExtensions.IsNull(object)
  • Edit this page
  • View Source
In this article
Back to top Copyright 2023 - Licensed under the MIT license by Michael Winsor (Tape_Worm).
Send comments on this topic to the author