public void Uninitialise() { try { lock (m_objLock) { if (!IsInitialised()) { throw new InvalidOperationException("Cannot unitialise plugin assembly; it isn't initialised"); } // If there are any plugin instances they need tearing down if (m_dictInstances != null && m_dictInstances.Count > 0) { foreach (var instance in m_dictInstances.Values.SelectMany(l => l).Where(l => l.IsInitialised())) { instance.Unitialise(); } } m_asmManager = null; try { AppDomain.Unload(m_adAssemblyAppDomain); } catch (Exception ex) { throw new ApplicationException("Failed to unload plugin assembly AppDomain", ex); } m_adAssemblyAppDomain = null; m_bIsInitialised = false; } } catch (Exception ex) { throw new ApplicationException("Failed to unitialise plugin assembly", ex); } }
/// <summary> /// Performs initialisation and loads the assembly /// </summary> public DistribPluginAssemblyInitialisationResult Initialise() { DistribPluginAssemblyInitialisationResult result = new DistribPluginAssemblyInitialisationResult(); try { lock (m_objLock) { if (IsInitialised()) { throw new InvalidOperationException("Cannot initialise plugin assembly; it is already initialised"); } // Set up the AppDomain m_adAssemblyAppDomain = AppDomain.CreateDomain(Guid.NewGuid() + "_" + m_strAssemblyPath); try { // Create the assembly manager for the plugin assembly isolated in the AppDomain m_asmManager = (DistribPluginAssemblyManager)m_adAssemblyAppDomain .CreateInstanceAndUnwrap( typeof(DistribPluginAssemblyManager).Assembly.FullName, typeof(DistribPluginAssemblyManager).FullName, true, System.Reflection.BindingFlags.CreateInstance, null, new object[] { m_strAssemblyPath }, null, null); } catch (Exception ex) { throw new ApplicationException("Failed to create manager in AppDomain", ex); } if (m_asmManager == null) { throw new ApplicationException("Manager in AppDomain was null after creation"); } try { // Load the assembly into the domain m_asmManager.LoadAssembly(); } catch (Exception ex) { throw new ApplicationException("Manager failed to load assembly into AppDomain", ex); } // Retrieve the details for all plugins present in the assembly // At this point these are the details that should be utilised by the developer and the system // for *actual* work as they are serialised through the AppDomain and as a result // any modifications here are not represented in the manager (usability etc) // When pushing down to the manager to perform low-level work, the type-name is used as the key // and the plugin details data will simply be used from the version given to the manager. m_lstPluginDetails = m_asmManager.GetPluginDetails(); if (m_lstPluginDetails == null || m_lstPluginDetails.Count == 0) { throw new InvalidOperationException("The plugin assembly contains no Distrib Plugins"); } // Go through all the plugins in the assembly foreach (var pluginType in m_lstPluginDetails) { // Do any bootstrapping that's required to fill in defaults etc // This has to be done before checking the usability as it could // affect things. var bootstrapResult = _PerformPluginBootstrapping(pluginType); if (!bootstrapResult.Success) { pluginType.MarkAsUnusable(PluginExclusionReason.PluginBootstrapFailure, bootstrapResult.Result); result.AddPlugin(pluginType); continue; } // Check over the usability of the plugin and mark it accordingly var usabilityCheckResult = _CheckUsabilityOfPlugin(pluginType); if (!usabilityCheckResult.Success) { pluginType.MarkAsUnusable(usabilityCheckResult.Result, usabilityCheckResult.ResultTwo); result.AddPlugin(pluginType); continue; } // Make sure that the additional metadata meets the existence / instancing requirements specified var metadataConstraintsResult = _CheckAdditionalMetadataExistenceRequirements(pluginType); if (!metadataConstraintsResult.Success) { pluginType.MarkAsUnusable(PluginExclusionReason.PluginAdditionalMetadataConstraintsNotMet, metadataConstraintsResult.Result); result.AddPlugin(pluginType); continue; } pluginType.MarkAsUsable(); result.AddPlugin(pluginType); } m_bIsInitialised = true; } // Lock the result to ensure no modifications result.LockResult(); return result; } catch (ReflectionTypeLoadException ex) { // Something has gone wrong when trying to load the types in the plugin // Mostly owing to missing references / plugins not adhering to interfaces var loaderExceptions = ex.LoaderExceptions; var sb = new StringBuilder(); sb.AppendLine("Failed to initialise plugin assembly, type loading errors:"); foreach (var te in loaderExceptions) { sb.AppendLine(te.Message); } throw new ApplicationException(sb.ToString(), ex); } catch (Exception ex) { throw new ApplicationException("Failed to initialise plugin assembly", ex); } }