Esempio n. 1
0
        /// <summary>
        /// Validates the list of plugins loaded by MEF.
        /// </summary>
        public void ValidatePlugins(ISplashView splashView)
        {
            _plugins.Clear();

            var dict = new Dictionary <Guid, BasePlugin>();

            if (_mefPlugins == null)
            {
                return;
            }

            foreach (var item in _mefPlugins)
            {
                var p = item.Value as BasePlugin;
                if (p == null)
                {
                    Logger.Current.Warn("Invalid plugin type: plugin must inherit from BasePlugin type.");
                    continue;
                }

                try
                {
                    p.Identity = PluginIdentityHelper.GetIdentity(p.GetType(), item.Metadata);
                }
                catch (Exception ex)
                {
                    throw new ApplicationException("Failed to load plugin identity from assembly.", ex);
                }

                // TODO: make sure that application plugins will have priority if duplicate GUIDs are found
                if (dict.ContainsKey(p.Identity.Guid))
                {
                    var    p2  = dict[p.Identity.Guid];
                    string msg = string.Format("Plugins have duplicate GUIDs: {0} {1}", p, p2);
                    throw new ApplicationException(msg);
                }
                splashView.ShowStatus("正在检查:" + p.Description);
                dict.Add(p.Identity.Guid, p);

                _container.RegisterInstance(p.GetType(), p);

                _plugins.Add(p);
            }

#if DEBUG
            // I didn't caught anything by this check so far;
            // Perhaps better just to check for particular assemblies in Plugins folder
            // and display warning if they are present
            CheckDuplicatedAssemblies();
#endif
        }
Esempio n. 2
0
        private Tuple <int, List <Lazy <IPlugin, IPluginMetadata> > > SortPluginsFor(
            Lazy <IPlugin, IPluginMetadata> currentItem,
            List <Lazy <IPlugin, IPluginMetadata> > pickList,
            List <Lazy <IPlugin, IPluginMetadata> > resultList)
        {
            // No more items to process?
            if (currentItem == null)
            {
                return(Tuple.Create(-1, resultList));
            }

            // Check if item is already processed:
            if (resultList.Contains(currentItem))
            {
                return(Tuple.Create(resultList.IndexOf(currentItem), resultList));
            }

            // Satisfy before dependents
            var minIndex = int.MaxValue;

            foreach (var beforeName in currentItem.Metadata.Before)
            {
                // Find the dependency
                var dependency = pickList.FirstOrDefault(i => {
                    if (!i.Metadata.Empty)
                    {
                        return(i.Metadata.Name == beforeName);
                    }
                    else
                    {
                        return(PluginIdentityHelper.GetIdentity(i.Value.GetType(), i.Metadata).Name == beforeName);
                    }
                });
                if (dependency == null)
                {
                    Logger.Current.Info($"Could not find before dependency '{beforeName}' for plugin '{currentItem.Value}'");
                    return(Tuple.Create(-1, resultList)); // bail out - this plugins dependencies aren't satisfied
                }

                // Get  the index of the dependecy
                var beforeIndex = resultList.IndexOf(dependency);
                if (beforeIndex < 0) // not in the result list yet
                {
                    // Resolve the dependency's order
                    var sortResult = SortPluginsFor(dependency, pickList, resultList);
                    beforeIndex = sortResult.Item1;
                    resultList  = sortResult.Item2;
                    if (beforeIndex < 0)
                    {
                        Logger.Current.Info($"Could not satisfy before dependency '{beforeName}' for plugin '{currentItem.Value}'");
                        return(Tuple.Create(-1, resultList)); // bail out - this plugins dependencies aren't satisfied
                    }
                }

                // Keep track of the lowest index
                if (minIndex > beforeIndex)
                {
                    minIndex = beforeIndex;
                }
            }

            // Satisfy after dependencies
            var maxIndex = 0;

            foreach (var afterName in currentItem.Metadata.After)
            {
                // Find the dependency
                var dependency = pickList.FirstOrDefault(i => {
                    if (!i.Metadata.Empty)
                    {
                        return(i.Metadata.Name == afterName);
                    }
                    else
                    {
                        return(PluginIdentityHelper.GetIdentity(i.Value.GetType(), i.Metadata).Name == afterName);
                    }
                });
                if (dependency == null)
                {
                    Logger.Current.Info($"Could not find after dependency '{afterName}' for plugin '{currentItem.Value}'");
                    return(Tuple.Create(-1, resultList)); // bail out - this plugins dependencies aren't satisfied
                }

                // Get  the index of the dependecy
                var afterIndex = resultList.IndexOf(dependency);
                if (afterIndex < 0) // not in the result list yet
                {
                    // Resolve the dependency's order
                    var sortResult = SortPluginsFor(dependency, pickList, resultList);
                    afterIndex = sortResult.Item1;
                    resultList = sortResult.Item2;
                    if (afterIndex < 0)
                    {
                        Logger.Current.Info($"Could not satisfy after dependency '{afterName}' for plugin '{currentItem.Value}'");
                        return(Tuple.Create(-1, resultList)); // bail out - this plugins dependencies aren't satisfied
                    }

                    // We want it to be inserted AFTER this:
                    afterIndex++;
                }

                // Keep track of the lowest index
                if (maxIndex < afterIndex)
                {
                    maxIndex = afterIndex;
                }
            }

            // If we have restrictions in both directions, ensure we can meet them both:
            if (currentItem.Metadata.Before.Any() && currentItem.Metadata.After.Any() && minIndex >= maxIndex)
            {
                Logger.Current.Info($"Could not satisfy dependency restrictions for plugin '{currentItem.Value}'");
                return(Tuple.Create(-1, resultList)); // bail out - this plugins dependencies aren't satisfied
            }

            // Insert item at highest possible index
            resultList.Insert(maxIndex, currentItem);

            return(Tuple.Create(maxIndex, resultList));
        }