public Res<PluginExclusionReason, object> CheckCoreUsability(IPluginDescriptor descriptor, IPluginAssemblyManager assemblyManager) { var res = PluginExclusionReason.Unknown; object resultAddit = null; bool success = true; if (descriptor == null) throw new ArgumentNullException("Descriptor must be supplied"); if (assemblyManager == null) throw new ArgumentNullException("Assembly manager must be supplied"); try { var _result = CChain<Tuple<PluginExclusionReason, object>> // Check the plugin's identifier is unique .If(() => assemblyManager.GetPluginDescriptors().Count(pd => pd.Metadata.Identifier == descriptor.Metadata.Identifier) > 1, new Tuple<PluginExclusionReason, object>(PluginExclusionReason.PluginIdentifierNotUnique, // Get all the other type names that are plugins sharing the identifier assemblyManager.GetPluginDescriptors() .Where(d => d.Metadata.Identifier == descriptor.Metadata.Identifier && d.PluginTypeName != descriptor.PluginTypeName) .Select(d => d.PluginTypeName) .ToList() .AsReadOnly())) // Check the plugin is marshalable .ThenIf(() => !assemblyManager.PluginTypeIsMarshalable(descriptor), new Tuple<PluginExclusionReason, object>(PluginExclusionReason.TypeNotCrossAppDomainObject, null)) // Check it implements the IPlugin interface .ThenIf(() => !assemblyManager.PluginTypeImplementsCorePluginInterface(descriptor), new Tuple<PluginExclusionReason,object>(PluginExclusionReason.CorePluginInterfaceNotImplemented, null)) // Check it implements the specific plugin interface it claims to .ThenIf(() => !assemblyManager.PluginTypeImplementsPromisedInterface(descriptor), new Tuple<PluginExclusionReason,object>(PluginExclusionReason.NonAdherenceToInterface, null)) .Result; if (_result == null) { success = true; res = PluginExclusionReason.Unknown; resultAddit = null; } else { success = false; res = _result.Item1; resultAddit = _result.Item2; } return new Res<PluginExclusionReason, object>((success &= true), res, resultAddit); } catch (Exception ex) { throw new ApplicationException("Failed to check core usability of plugin", ex); } }
public IPluginAssemblyInitialisationResult Initialise() { List<IPluginDescriptor> lstPluginDescriptorsForResult = new List<IPluginDescriptor>(); try { lock (_lock) { if (IsInitialised) { throw new InvalidOperationException("Plugin assembly already initialised"); } // Set up the AppDomain _appDomain = AppDomain.CreateDomain(Guid.NewGuid() + "_" + _netAssemblyPath); try { // Create the assembly manager _assemblyManager = _asmManagerFactory.CreateManagerForAssemblyInGivenDomain( _netAssemblyPath, _appDomain); } catch (Exception ex) { throw new ApplicationException("Failed to create assembly manager", ex); } // Need to make sure a manager is present if (_assemblyManager == null) { throw new ApplicationException("Manager was null after attempted creation"); } try { // Load the assembly into the domain _assemblyManager.LoadPluginAssemblyIntoDomain(); } catch (Exception ex) { throw new ApplicationException("Failed to load assembly into AppDomain", ex); } // Pull out the plugin descriptors _pluginDescriptors = _assemblyManager.GetPluginDescriptors(); if (_pluginDescriptors == null || _pluginDescriptors.Count == 0) { throw new InvalidOperationException("Plugin assembly contains no plugins"); } foreach (IPluginDescriptor descriptor in _pluginDescriptors) { // Perform the bootstrapping for the plugin var bootstrapResult = _pluginBootstrapService.BootstrapPlugin(descriptor); if (!bootstrapResult.Success) { descriptor.MarkAsUnusable(PluginExclusionReason.PluginBootstrapFailure, bootstrapResult.Result); lstPluginDescriptorsForResult.Add(descriptor); continue; } // Perform the core usability checking var usabilityCheckResult = _pluginCoreUsabilityCheckService .CheckCoreUsability(descriptor, _assemblyManager); if (!usabilityCheckResult.Success) { descriptor.MarkAsUnusable(usabilityCheckResult.Result, usabilityCheckResult.ResultTwo); lstPluginDescriptorsForResult.Add(descriptor); continue; } // Perform the verification for usability of the plugin controller var controllerValidationResult = _pluginControllerValidationService .ValidateControllerType(descriptor.Metadata.ControllerType); if (!controllerValidationResult.Success) { descriptor.MarkAsUnusable(PluginExclusionReason.PluginControllerInvalid, controllerValidationResult.ResultTwo); lstPluginDescriptorsForResult.Add(descriptor); continue; } // Make sure the additional metadata bundles adhere to their constraints var metadataConstraintsCheckResult = _pluginMetadataBundleCheckService .CheckMetadataBundlesFulfilConstraints(descriptor.AdditionalMetadataBundles); if (!metadataConstraintsCheckResult.Success) { descriptor.MarkAsUnusable(PluginExclusionReason.PluginAdditionalMetadataConstraintsNotMet, metadataConstraintsCheckResult.Result); lstPluginDescriptorsForResult.Add(descriptor); continue; } // Made it this far so mark as usable descriptor.MarkAsUsable(); lstPluginDescriptorsForResult.Add(descriptor); } // Mark as initialised _isInitialised = true; return _pluginAsmInitialisationResultFactory .CreateResultFromPlugins(lstPluginDescriptorsForResult.AsReadOnly()); } } catch (ReflectionTypeLoadException ex) { // Something went wrong trying to load types in the plugin 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); } }