示例#1
0
        public PluginInfo(Type type, PluginSetConstructionInfo constructionInfo)
        {
            Type      = type;
            Ancestors = ImmutableArray.Create(
                type.GetAllBaseTypes().Select(t => (TypeRef)t).ToArray());
            Interfaces = ImmutableArray.Create(
                type.GetInterfaces().Select(t => (TypeRef)t).ToArray());
            CastableTo = ImmutableHashSet.Create(
                Ancestors.AddRange(Interfaces).Add(type).ToArray());
            Capabilities = ImmutableDictionary <string, object> .Empty;
            Dependencies = ImmutableHashSet <TypeRef> .Empty;

            object?tmpPlugin = null;

            try {
                tmpPlugin = constructionInfo.PluginFactory.Create(type);
            }
            catch (Exception) {
                // There might be plugins we can't construct -- mainly,
                // b/c their constructors aren't written properly to support
                // temporary plugin factory.
                // All we can do here is to ignore this exception & assume
                // these plugins can't provide capabilities and dependencies.
            }

            if (tmpPlugin is IHasCapabilities hc)
            {
                Capabilities = hc.Capabilities;
            }
            if (tmpPlugin is IHasDependencies hd)
            {
                Dependencies = hd.Dependencies.Select(t => (TypeRef)t).ToImmutableHashSet();
            }

            var allAssemblyRefs = constructionInfo.AllAssemblyRefs[type.Assembly];

            AllDependencies = constructionInfo.Plugins
                              .Where(p => p != type && (
                                         allAssemblyRefs.Contains(p.Assembly) ||
                                         CastableTo.Contains(p)))
                              .Select(t => (TypeRef)t)
                              .Concat(Dependencies)
                              .ToImmutableHashSet();
        }
示例#2
0
        public PluginSetInfo(IEnumerable <Type> plugins)
        {
            var ci = new PluginSetConstructionInfo()
            {
                Plugins = plugins.ToArray(),
            };

            if (ci.Plugins.Length == 0)
            {
                // Super important to have this case handled explicitly.
                // Otherwise the initializer for PluginContainerConfiguration.Empty
                // will fail due to recursion here & attempt to register null as a
                // singleton inside BuildContainer call below.
                InfoByType      = ImmutableDictionary <TypeRef, PluginInfo> .Empty;
                TypesByBaseType = ImmutableDictionary <TypeRef, ImmutableHashSet <TypeRef> > .Empty;
                TypesByBaseTypeOrderedByDependency = ImmutableDictionary <TypeRef, ImmutableArray <TypeRef> > .Empty;
                return;
            }

            HashSet <Assembly> GetAllDependencies(Assembly assembly, HashSet <Assembly>?result = null)
            {
                result ??= new HashSet <Assembly>();
                foreach (var referenceName in assembly.GetReferencedAssemblies())
                {
                    var reference = Assembly.Load(referenceName);
                    if (result.Add(reference))
                    {
                        GetAllDependencies(reference, result);
                    }
                }
                return(result);
            }

            var hAssemblies = ci.Plugins.Select(t => t.Assembly).ToHashSet();

            ci.AllAssemblyRefs = hAssemblies
                                 .Select(a => (
                                             Assembly: a,
                                             Refs: GetAllDependencies(a)
                                             .Where(a => hAssemblies.Contains(a))
                                             .ToHashSet()))
                                 .ToDictionary(p => p.Assembly, p => p.Refs);
            ci.Assemblies = hAssemblies
                            .OrderByDependency(a =>
                                               ci.AllAssemblyRefs.GetValueOrDefault(a) ?? Enumerable.Empty <Assembly>())
                            .ToArray();
            ci.PluginFactory = new PluginHostBuilder()
                               .ConfigureServices((builder, services) => {
                services.AddSingleton <IPluginInfoQuery>(new PluginInfoQuery());
                services.AddSingleton <IPluginFactory>(s => new QueryingPluginFactory(s));
            })
                               .SetAutoStart(false)
                               .Build()
                               .GetRequiredService <IPluginFactory>();

            var dPlugins         = new Dictionary <TypeRef, PluginInfo>();
            var dTypesByBaseType = new Dictionary <TypeRef, ImmutableHashSet <TypeRef> >();

            foreach (var plugin in ci.Plugins)
            {
                var pluginInfo = new PluginInfo(plugin, ci);
                dPlugins.Add(plugin, pluginInfo);
                foreach (var baseType in pluginInfo.CastableTo)
                {
                    var existingImpls = dTypesByBaseType.GetValueOrDefault(baseType)
                                        ?? ImmutableHashSet <TypeRef> .Empty;
                    dTypesByBaseType[baseType] = existingImpls.Add(pluginInfo.Type);
                }
            }

            var orderedPlugins = dPlugins.Values
                                 .OrderByDependency(p => p.AllDependencies.Select(t => dPlugins[t]))
                                 .ToArray();

            for (var i = 0; i < orderedPlugins.Length; i++)
            {
                orderedPlugins[i].OrderByDependencyIndex = i;
            }

            InfoByType      = dPlugins.ToImmutableDictionary();
            TypesByBaseType = dTypesByBaseType.ToImmutableDictionary();
            TypesByBaseTypeOrderedByDependency = dTypesByBaseType
                                                 .Select(p => new KeyValuePair <TypeRef, ImmutableArray <TypeRef> >(
                                                             p.Key,
                                                             p.Value
                                                             .OrderBy(t => dPlugins[t].OrderByDependencyIndex)
                                                             .ToImmutableArray()))
                                                 .ToImmutableDictionary();
        }