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);
            }
        }
示例#2
0
        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);
            }
        }