private void ProcessFeatureDescriptor(ShapeTableBuilder builder, FeatureDescriptor featureDescriptor)
 {
     var virtualPath = featureDescriptor.Extension.Location + "/" + featureDescriptor.Extension.Id + "/Placement.info";
     var placementFile = _placementFileParser.Parse(virtualPath);
     if (placementFile != null)
     {
         ProcessPlacementFile(builder, featureDescriptor, placementFile);
     }
 }
        private static IEnumerable<FeatureDescriptor> GetFeaturesForExtension(IDictionary<string, string> manifest, ExtensionDescriptorEntry entry)
        {
            var featureDescriptors = new List<FeatureDescriptor>();

            var descriptor = entry.Descriptor;
            //默认特性
            var defaultFeature = new FeatureDescriptor
            {
                Id = entry.Id,
                Name = GetValue(manifest, FeatureNameSection) ?? descriptor.Name,
                Priority = GetValue(manifest, PrioritySection) != null ? int.Parse(GetValue(manifest, PrioritySection)) : 0,
                Description = GetValue(manifest, FeatureDescriptionSection) ?? GetValue(manifest, DescriptionSection) ?? string.Empty,
                Dependencies = ParseFeatureDependenciesEntry(GetValue(manifest, DependenciesSection)),
                Extension = entry,
                Category = GetValue(manifest, CategorySection)
            };

            featureDescriptors.Add(defaultFeature);

            //剩余特性
            var featuresText = GetValue(manifest, FeaturesSection);
            if (string.IsNullOrWhiteSpace(featuresText))
                return featureDescriptors;
            FeatureDescriptor featureDescriptor = null;
            using (var reader = new StringReader(featuresText))
            {
                string line;
                while ((line = reader.ReadLine()) != null)
                {
                    if (IsFeatureDeclaration(line))
                    {
                        if (featureDescriptor != null)
                        {
                            if (!featureDescriptor.Equals(defaultFeature))
                            {
                                featureDescriptors.Add(featureDescriptor);
                            }
                        }

                        var featureDeclaration = line.Split(new[] { ":" }, StringSplitOptions.RemoveEmptyEntries);
                        var featureDescriptorId = featureDeclaration[0].Trim();
                        if (string.Equals(featureDescriptorId, entry.Id, StringComparison.OrdinalIgnoreCase))
                        {
                            featureDescriptor = defaultFeature;
                            featureDescriptor.Name = descriptor.Name;
                        }
                        else
                        {
                            featureDescriptor = new FeatureDescriptor
                            {
                                Id = featureDescriptorId,
                                Extension = entry
                            };
                        }
                    }
                    else if (IsFeatureFieldDeclaration(line))
                    {
                        if (featureDescriptor != null)
                        {
                            var featureField = line.Split(new[] { ":" }, 2, StringSplitOptions.None);
                            var featureFieldLength = featureField.Length;
                            if (featureFieldLength != 2)
                                continue;
                            for (var i = 0; i < featureFieldLength; i++)
                            {
                                featureField[i] = featureField[i].Trim();
                            }

                            switch (featureField[0].ToLowerInvariant())
                            {
                                case NameSection:
                                    featureDescriptor.Name = featureField[1];
                                    break;

                                case DescriptionSection:
                                    featureDescriptor.Description = featureField[1];
                                    break;

                                case CategorySection:
                                    featureDescriptor.Category = featureField[1];
                                    break;

                                case PrioritySection:
                                    featureDescriptor.Priority = int.Parse(featureField[1]);
                                    break;

                                case DependenciesSection:
                                    featureDescriptor.Dependencies = ParseFeatureDependenciesEntry(featureField[1]);
                                    break;
                            }
                        }
                        else
                        {
                            var message = string.Format("行 {0} 在清单文件中被忽略,来自扩展 {1}", line, entry.Id);
                            throw new ArgumentException(message);
                        }
                    }
                    else
                    {
                        var message = string.Format("行 {0} 在清单文件中被忽略,来自扩展 {1}", line, entry.Id);
                        throw new ArgumentException(message);
                    }
                }

                if (featureDescriptor != null && !featureDescriptor.Equals(defaultFeature))
                    featureDescriptors.Add(featureDescriptor);
            }

            return featureDescriptors;
        }
        /// <summary>
        /// 如果该项目有关于这个问题的明确或隐含的依赖关系,则返回true
        /// </summary>
        internal static bool HasDependency(FeatureDescriptor item, FeatureDescriptor subject)
        {
            if (DefaultExtensionTypes.IsTheme(item.Extension.ExtensionType))
            {
                if (DefaultExtensionTypes.IsModule(subject.Extension.ExtensionType))
                {
                    //主题含蓄地依赖于模块,以确保构建和覆盖排序
                    return true;
                }

                if (DefaultExtensionTypes.IsTheme(subject.Extension.ExtensionType))
                {
                    //主题取决于另一个如果这是它的基本主题
                    return item.Extension.Descriptor.GetBaseTheme() == subject.Id;
                }
            }

            //基于显式依赖关系返回
            return item.Dependencies != null &&
                   item.Dependencies.Any(x => StringComparer.OrdinalIgnoreCase.Equals(x, subject.Id));
        }
 private bool FeatureIsEnabled(FeatureDescriptor fd)
 {
     return (DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType) && (fd.Id == "TheAdmin" || fd.Id == "SafeMode")) ||
         _shellDescriptor.Features.Any(sf => sf.Name == fd.Id);
 }
 /// <summary>
 /// 初始化一个新的特性描述符过滤器上下文。
 /// </summary>
 /// <param name="feature">特性描述符。</param>
 public FeatureDescriptorFilterContext(FeatureDescriptor feature)
 {
     Feature = feature;
     Valid = true;
 }
        private static void ProcessPlacementFile(ShapeTableBuilder builder, FeatureDescriptor featureDescriptor, PlacementFile placementFile)
        {
            var feature = new Feature { Descriptor = featureDescriptor };

            //反转树成叶子的列表,并在堆栈
            var entries = DrillDownShapeLocations(placementFile.Nodes, Enumerable.Empty<PlacementMatch>());
            foreach (var entry in entries)
            {
                var shapeLocation = entry.Item1;
                var matches = entry.Item2.ToArray();

                string shapeType;
                string differentiator;
                GetShapeType(shapeLocation, out shapeType, out differentiator);

                Func<ShapePlacementContext, bool> predicate = ctx => true;
                if (differentiator != string.Empty)
                {
                    predicate = ctx => (ctx.Differentiator ?? string.Empty) == differentiator;
                }

                if (matches.Any())
                {
                    predicate = matches.SelectMany(match => match.Terms).Aggregate(predicate, BuildPredicate);
                }

                var placement = new PlacementInfo();

                var segments = shapeLocation.Location.Split(';').Select(s => s.Trim());
                foreach (var segment in segments)
                {
                    if (!segment.Contains('='))
                    {
                        placement.Location = segment;
                    }
                    else
                    {
                        var index = segment.IndexOf('=');
                        var property = segment.Substring(0, index).ToLower();
                        var value = segment.Substring(index + 1);
                        switch (property)
                        {
                            case "shape":
                                placement.ShapeType = value;
                                break;

                            case "alternate":
                                placement.Alternates = new[] { value };
                                break;

                            case "wrapper":
                                placement.Wrappers = new[] { value };
                                break;
                        }
                    }
                }

                builder.Describe(shapeType)
                    .From(feature)
                    .Placement(ctx =>
                    {
                        var hit = predicate(ctx);
                        //产生'调试'信息跟踪哪个文件起源的实际位置
                        if (hit)
                        {
                            var virtualPath = featureDescriptor.Extension.Location + "/" + featureDescriptor.Extension.Id + "/Placement.info";
                            ctx.Source = virtualPath;
                        }
                        return hit;
                    }, placement);
            }
        }
 private bool FeatureIsEnabled(FeatureDescriptor fd)
 {
     return _shellDescriptor.Features.Any(sf => sf.Name == fd.Id);
 }
 private static bool FeatureIsTheme(FeatureDescriptor fd)
 {
     return DefaultExtensionTypes.IsTheme(fd.Extension.ExtensionType);
 }
        private Feature LoadFeature(FeatureDescriptor featureDescriptor)
        {
            var extensionDescriptor = featureDescriptor.Extension;
            var featureId = featureDescriptor.Id;
            var extensionId = extensionDescriptor.Id;

            ExtensionEntry extensionEntry;
            try
            {
                extensionEntry = _cacheManager.Get(extensionId, ctx =>
                {
                    var entry = BuildEntry(extensionDescriptor);
                    if (entry != null)
                    {
                        ctx.Monitor(_asyncTokenProvider.GetToken(monitor =>
                        {
                            foreach (var loader in _loaders.Value)
                            {
                                loader.Monitor(entry.Descriptor, monitor);
                            }
                        }));
                    }
                    return entry;
                });
            }
            catch (Exception ex)
            {
                Logger.Error(ex, "加载扩展 '{0}' 失败", extensionId);
                throw new RabbitException(T("加载扩展 '{0}' 失败。", extensionId), ex);
            }

            if (extensionEntry == null)
            {
                //如果该功能因为某种原因不能被编译,返回一个"null"的特性,即没有输出的类型的功能。
                return new Feature
                {
                    Descriptor = featureDescriptor,
                    ExportedTypes = Enumerable.Empty<Type>()
                };
            }

            var extensionTypes = _serviceTypeHarvester.GeTypes(extensionEntry.ExportedTypes);

            var featureTypes = extensionTypes.Where(
                i =>
                    string.Equals(GetSourceFeatureNameForType(i, extensionId), featureId,
                        StringComparison.OrdinalIgnoreCase)).ToArray();

            return new Feature
            {
                Descriptor = featureDescriptor,
                ExportedTypes = featureTypes
            };
        }
 private static int GetPriority(FeatureDescriptor featureDescriptor)
 {
     return featureDescriptor.Priority;
 }
 private static bool HasDependency(FeatureDescriptor item, FeatureDescriptor subject)
 {
     return item.Dependencies != null &&
            item.Dependencies.Any(x => StringComparer.OrdinalIgnoreCase.Equals(x, subject.Id));
 }