public IEnumerable<HarvestShapeHit> HarvestShape(HarvestShapeInfo info)
 {
     var lastDash = info.FileName.LastIndexOf('-');
     var lastDot = info.FileName.LastIndexOf('.');
     if (lastDot <= 0 || lastDot < lastDash)
     {
         yield return new HarvestShapeHit
         {
             ShapeType = Adjust(info.SubPath, info.FileName, null)
         };
     }
     else
     {
         var displayType = info.FileName.Substring(lastDot + 1);
         yield return new HarvestShapeHit
         {
             ShapeType = Adjust(info.SubPath, info.FileName.Substring(0, lastDot), displayType),
             DisplayType = displayType
         };
     }
 }
        private IHtmlString Render(DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo)
        {
            Logger.Information("渲染模板文件 '{0}'", harvestShapeInfo.TemplateVirtualPath);
            IHtmlString result;

            if (displayContext.ViewContext.View != null)
            {
                var htmlHelper = new HtmlHelper(displayContext.ViewContext, displayContext.ViewDataContainer);
                result = htmlHelper.Partial(harvestShapeInfo.TemplateVirtualPath, displayContext.Value);
            }
            else
            {
                //如果视图为空,则表示该造型是从一个非视图产地/在没有的ViewContext成立了由视图引擎,但是手动执行。
                //手动创建的ViewContext工程与形状的方法工作时,而不是当形状被实现为一个Razor视图模板。
                //可怕的,但它会做现在。
                result = RenderRazorViewToString(harvestShapeInfo.TemplateVirtualPath, displayContext);
            }

            Logger.Information("完成目标文件 '{0}' 的渲染。", harvestShapeInfo.TemplateVirtualPath);
            return(result);
        }
        public IEnumerable <HarvestShapeHit> HarvestShape(HarvestShapeInfo info)
        {
            var lastDash = info.FileName.LastIndexOf('-');
            var lastDot  = info.FileName.LastIndexOf('.');

            if (lastDot <= 0 || lastDot < lastDash)
            {
                yield return(new HarvestShapeHit
                {
                    ShapeType = Adjust(info.SubPath, info.FileName, null)
                });
            }
            else
            {
                var displayType = info.FileName.Substring(lastDot + 1);
                yield return(new HarvestShapeHit
                {
                    ShapeType = Adjust(info.SubPath, info.FileName.Substring(0, lastDot), displayType),
                    DisplayType = displayType
                });
            }
        }
        public void Discover(ShapeTableBuilder builder)
        {
            Logger.Information("开始发现形状");

            var harvesterInfos = _harvesters.Select(harvester => new { harvester, subPaths = harvester.SubPaths() });

            var availableFeatures = _extensionManager.AvailableFeatures();
            var activeFeatures = availableFeatures.Where(FeatureIsEnabled);
            var activeExtensions = Once(activeFeatures);

            var hits = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor =>
            {
                Logger.Information("开始发现候选视图文件名称");
                var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath =>
                {
                    var basePath = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
                    var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
                    var fileNames = _cacheManager.Get(virtualPath, ctx =>
                    {
                        if (!_virtualPathProvider.DirectoryExists(virtualPath))
                            return new string[0];

                        if (!DisableMonitoring)
                        {
                            Logger.Debug("监控虚拟路径 \"{0}\"", virtualPath);
                            ctx.Monitor(_virtualPathMonitor.WhenPathChanges(virtualPath));
                        }

                        return _virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName).ToArray();
                    });
                    return new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames };
                })).ToList();
                Logger.Information("发现候选视图文件名称完成");

                var fileContexts = pathContexts.SelectMany(pathContext => _shapeTemplateViewEngines.SelectMany(ve =>
                {
                    var fileNames = ve.DetectTemplateFileNames(pathContext.fileNames);
                    return fileNames.Select(
                        fileName => new
                        {
                            fileName = Path.GetFileNameWithoutExtension(fileName),
                            fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace(Path.DirectorySeparatorChar, '/'),
                            pathContext
                        });
                }));

                var shapeContexts = fileContexts.SelectMany(fileContext =>
                {
                    var harvestShapeInfo = new HarvestShapeInfo
                    {
                        SubPath = fileContext.pathContext.subPath,
                        FileName = fileContext.fileName,
                        TemplateVirtualPath = fileContext.fileVirtualPath
                    };
                    var harvestShapeHits = fileContext.pathContext.harvester.HarvestShape(harvestShapeInfo);
                    return harvestShapeHits.Select(harvestShapeHit => new { harvestShapeInfo, harvestShapeHit, fileContext });
                });

                return shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext }).ToList();
            }).SelectMany(hits2 => hits2);

            foreach (var iter in hits)
            {
                //模板总是与模块或主题的同名特征相关联
                var hit = iter;
                var featureDescriptors = iter.extensionDescriptor.Descriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id);
                foreach (var featureDescriptor in featureDescriptors)
                {
                    Logger.Debug("为特性 {2} 绑定 {0} 到形状 [{1}]",
                        hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                        iter.shapeContext.harvestShapeHit.ShapeType,
                        featureDescriptor.Id);

                    builder.Describe(iter.shapeContext.harvestShapeHit.ShapeType)
                        .From(new Feature { Descriptor = featureDescriptor })
                        .BoundAs(
                            hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                            shapeDescriptor => displayContext => Render(displayContext, hit.shapeContext.harvestShapeInfo));
                }
            }

            Logger.Information("形状发现完成。");
        }
        private IHtmlString Render(DisplayContext displayContext, HarvestShapeInfo harvestShapeInfo)
        {
            Logger.Information("渲染模板文件 '{0}'", harvestShapeInfo.TemplateVirtualPath);
            IHtmlString result;

            if (displayContext.ViewContext.View != null)
            {
                var htmlHelper = new HtmlHelper(displayContext.ViewContext, displayContext.ViewDataContainer);
                result = htmlHelper.Partial(harvestShapeInfo.TemplateVirtualPath, displayContext.Value);
            }
            else
            {
                //如果视图为空,则表示该造型是从一个非视图产地/在没有的ViewContext成立了由视图引擎,但是手动执行。
                //手动创建的ViewContext工程与形状的方法工作时,而不是当形状被实现为一个Razor视图模板。
                //可怕的,但它会做现在。
                result = RenderRazorViewToString(harvestShapeInfo.TemplateVirtualPath, displayContext);
            }

            Logger.Information("完成目标文件 '{0}' 的渲染。", harvestShapeInfo.TemplateVirtualPath);
            return result;
        }
        public void Discover(ShapeTableBuilder builder)
        {
            Logger.Information("开始发现形状");

            var harvesterInfos = _harvesters.Select(harvester => new { harvester, subPaths = harvester.SubPaths() });

            var availableFeatures = _extensionManager.AvailableFeatures();
            var activeFeatures    = availableFeatures.Where(FeatureIsEnabled);
            var activeExtensions  = Once(activeFeatures);

            var hits = _parallelCacheContext.RunInParallel(activeExtensions, extensionDescriptor =>
            {
                Logger.Information("开始发现候选视图文件名称");
                var pathContexts = harvesterInfos.SelectMany(harvesterInfo => harvesterInfo.subPaths.Select(subPath =>
                {
                    var basePath    = Path.Combine(extensionDescriptor.Location, extensionDescriptor.Id).Replace(Path.DirectorySeparatorChar, '/');
                    var virtualPath = Path.Combine(basePath, subPath).Replace(Path.DirectorySeparatorChar, '/');
                    var fileNames   = _cacheManager.Get(virtualPath, ctx =>
                    {
                        if (!_virtualPathProvider.DirectoryExists(virtualPath))
                        {
                            return(new string[0]);
                        }

                        if (!DisableMonitoring)
                        {
                            Logger.Debug("监控虚拟路径 \"{0}\"", virtualPath);
                            ctx.Monitor(_virtualPathMonitor.WhenPathChanges(virtualPath));
                        }

                        return(_virtualPathProvider.ListFiles(virtualPath).Select(Path.GetFileName).ToArray());
                    });
                    return(new { harvesterInfo.harvester, basePath, subPath, virtualPath, fileNames });
                })).ToList();
                Logger.Information("发现候选视图文件名称完成");

                var fileContexts = pathContexts.SelectMany(pathContext => _shapeTemplateViewEngines.SelectMany(ve =>
                {
                    var fileNames = ve.DetectTemplateFileNames(pathContext.fileNames);
                    return(fileNames.Select(
                               fileName => new
                    {
                        fileName = Path.GetFileNameWithoutExtension(fileName),
                        fileVirtualPath = Path.Combine(pathContext.virtualPath, fileName).Replace(Path.DirectorySeparatorChar, '/'),
                        pathContext
                    }));
                }));

                var shapeContexts = fileContexts.SelectMany(fileContext =>
                {
                    var harvestShapeInfo = new HarvestShapeInfo
                    {
                        SubPath             = fileContext.pathContext.subPath,
                        FileName            = fileContext.fileName,
                        TemplateVirtualPath = fileContext.fileVirtualPath
                    };
                    var harvestShapeHits = fileContext.pathContext.harvester.HarvestShape(harvestShapeInfo);
                    return(harvestShapeHits.Select(harvestShapeHit => new { harvestShapeInfo, harvestShapeHit, fileContext }));
                });

                return(shapeContexts.Select(shapeContext => new { extensionDescriptor, shapeContext }).ToList());
            }).SelectMany(hits2 => hits2);

            foreach (var iter in hits)
            {
                //模板总是与模块或主题的同名特征相关联
                var hit = iter;
                var featureDescriptors = iter.extensionDescriptor.Descriptor.Features.Where(fd => fd.Id == hit.extensionDescriptor.Id);
                foreach (var featureDescriptor in featureDescriptors)
                {
                    Logger.Debug("为特性 {2} 绑定 {0} 到形状 [{1}]",
                                 hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                                 iter.shapeContext.harvestShapeHit.ShapeType,
                                 featureDescriptor.Id);

                    builder.Describe(iter.shapeContext.harvestShapeHit.ShapeType)
                    .From(new Feature {
                        Descriptor = featureDescriptor
                    })
                    .BoundAs(
                        hit.shapeContext.harvestShapeInfo.TemplateVirtualPath,
                        shapeDescriptor => displayContext => Render(displayContext, hit.shapeContext.harvestShapeInfo));
                }
            }

            Logger.Information("形状发现完成。");
        }