/// <summary>
        /// 创建一个外壳上下文工厂。
        /// </summary>
        /// <param name="settings">外壳设置。</param>
        /// <returns>外壳上下文。</returns>
        public ShellContext CreateShellContext(ShellSettings settings)
        {
            Logger.Debug("准备为租户 {0} 创建外壳上下文", settings.Name);

            var knownDescriptor = _shellDescriptorCache.Fetch(settings.Name);

            if (knownDescriptor == null)
            {
                Logger.Information("在缓存中找不到外壳描述符信息。 以最少的组件开始。");
                var features = new List <ShellFeature>();
                _minimumShellDescriptorProviders.Invoke(i => i.GetFeatures(features), Logger);
                knownDescriptor = MinimumShellDescriptor(features);
            }

            var blueprint  = _compositionStrategy.Compose(settings, knownDescriptor);
            var shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);

            ShellDescriptor currentDescriptor;

            using (var standaloneEnvironment = shellScope.CreateWorkContextScope())
            {
                var shellDescriptorManager = standaloneEnvironment.Resolve <IShellDescriptorManager>();
                currentDescriptor = shellDescriptorManager.GetShellDescriptor();
            }

            if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber)
            {
                currentDescriptor.Features = currentDescriptor.Features.Distinct(new ShellFeatureEqualityComparer()).ToArray();
                Logger.Information("获得较新的外壳描述符。重新构建外壳容器。");

                _shellDescriptorCache.Store(settings.Name, currentDescriptor);
                blueprint = _compositionStrategy.Compose(settings, currentDescriptor);
                shellScope.Dispose();
                shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);
            }

            return(new ShellContext
            {
                Settings = settings,
                Descriptor = currentDescriptor,
                Blueprint = blueprint,
                Container = shellScope,
                Shell = shellScope.Resolve <IShell>(),
            });
        }
        public ShellContext CreateShellContext(ShellSettings settings)
        {
            Logger.Debug("Creating shell context for tenant {0}", settings.Name);

            var knownDescriptor = _shellDescriptorCache.Fetch(settings.Name);

            if (knownDescriptor == null)
            {
                Logger.Information("No descriptor cached. Starting with minimum components.");
                knownDescriptor = MinimumShellDescriptor();
            }

            var blueprint  = _compositionStrategy.Compose(settings, knownDescriptor);
            var shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);

            ShellDescriptor currentDescriptor;

            using (var standaloneEnvironment = shellScope.CreateWorkContextScope())
            {
                var shellDescriptorManager = standaloneEnvironment.Resolve <IShellDescriptorManager>();
                currentDescriptor = shellDescriptorManager.GetShellDescriptor();
            }

            if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber)
            {
                Logger.Information("Newer descriptor obtained. Rebuilding shell container.");

                _shellDescriptorCache.Store(settings.Name, currentDescriptor);
                blueprint = _compositionStrategy.Compose(settings, currentDescriptor);
                shellScope.Dispose();
                shellScope = _shellContainerFactory.CreateContainer(settings, blueprint);
            }

            return(new ShellContext
            {
                Settings = settings,
                Descriptor = currentDescriptor,
                Blueprint = blueprint,
                LifetimeScope = shellScope,
                Shell = shellScope.Resolve <IBoyingShell>(),
            });
        }
Пример #3
0
        /// <summary>
        /// 创建 Shell 运行时上下文。
        /// </summary>
        /// <returns>创建的 <see cref="ShellContext"/> 实例。</returns>
        public ShellContext CreateShellContext()
        {
            _logger.WriteTrace($"正在为应用程序 {_options.AppName}({_options.AppSystemName}) 创建 Shell 。");

            var knownDescriptor = _shellDescriptorCache.Fetch(_options.AppName);

            if (knownDescriptor == null)
            {
                //本地没有存储蓝图信息,则先构建应用程序运行所需的最小蓝图。
                _logger.WriteTrace("找不到缓存的 SehllDescriptor 对象。将使用最小蓝图启动应用程序。");
                knownDescriptor = MinimumShellDescriptor();
            }
            //组装应用程序组件构建蓝图。
            var blueprint = _compositionStrategy.Compose(_options.AppName, knownDescriptor);

            ShellDescriptor currentDescriptor = _shellDescriptorManager.GetShellDescriptor();

            //首次运行 currentDescriptor 可能为空,将用最小蓝图启动程序。
            if (currentDescriptor != null && knownDescriptor.ApplicationName != currentDescriptor.ApplicationName)
            {
                _logger.WriteTrace("获得了新的 Shell 信息。 正在重新创建 Shell 蓝图。");

                _shellDescriptorCache.Store(_options.AppName, currentDescriptor);
                blueprint = _compositionStrategy.Compose(_options.AppName, currentDescriptor);
            }

            //注意,ConfigureBlueprint 为迭代器方法,对属性赋值时切勿直接赋值,应该先保证调用。
            //迭代器方法在实际使用时才会调用,更多请参考 C# 语言知识,这里先 ToArray 防止访问 ShellContext.Services 属性时造成多次调用。
            var descriptor = this.BuildDependencies(blueprint);

            return(new ShellContext
            {
                Descriptor = currentDescriptor ?? knownDescriptor,
                Blueprint = blueprint,
                Services = descriptor.Item1,
                EventSubscriptors = descriptor.Item2
            });
        }
        /// <summary>
        /// 获取当前外壳描述符。
        /// </summary>
        /// <returns>外壳描述符。</returns>
        public ShellDescriptor GetShellDescriptor()
        {
            //得到当前租户的外壳描述符。
            var descriptor = _shellDescriptorCache.Fetch(_settings.Name);

            //如果之前的记录与最新的功能描述符相等直接返回。
            if (descriptor != null)
            {
                return(descriptor);
            }

            //得到最新的功能描述符名称集合。
            var features = GetFeatures();

            //添加一个新的描述符。
            return(new ShellDescriptor
            {
                Features = features.Select(i => new ShellFeature {
                    Name = i
                }).ToArray(),
                SerialNumber = GetSerialNumber()
            });
        }
        public ShellContext CreateShellContext(ShellSettings settings)
        {
            Logger.DebugFormat("Creating shell context for tenant {0}", settings.Name);

            var knownDescriptor = shellDescriptorCache.Fetch(settings.Name);

            if (knownDescriptor == null)
            {
                Logger.Info("No descriptor cached. Starting with minimum components.");
                var multiTenancy = Convert.ToBoolean(ConfigurationManager.AppSettings["CMS.MultiTenancy"]);
                knownDescriptor = MinimumShellDescriptor(multiTenancy);
            }

            if (!string.IsNullOrEmpty(settings.DataProvider))
            {
                var provider = CMSConfigurationSection.Instance.Data.Providers[settings.DataProvider];
                if (provider != null)
                {
                    if (knownDescriptor.Features.All(x => x.Name != provider.Feature))
                    {
                        knownDescriptor.Features.Insert(1, new ShellFeature {
                            Name = provider.Feature
                        });
                    }
                }
            }

            var blueprint  = compositionStrategy.Compose(settings, knownDescriptor);
            var shellScope = shellContainerFactory.CreateContainer(settings, blueprint);

            ShellDescriptor currentDescriptor;

            using (var standaloneEnvironment = shellScope.CreateWorkContextScope())
            {
                var shellDescriptorManager = standaloneEnvironment.Resolve <IShellDescriptorManager>();
                currentDescriptor = shellDescriptorManager.GetShellDescriptor();

                if (currentDescriptor == null)
                {
                    shellDescriptorManager.UpdateShellDescriptor(0, knownDescriptor.Features, false);
                }
                else
                {
                    // Detect new auto activated features
                    if (knownDescriptor.SerialNumber == currentDescriptor.SerialNumber)
                    {
                        var features = new List <ShellFeature>(currentDescriptor.Features);
                        var hasNew   = false;
                        foreach (var feature in knownDescriptor.Features)
                        {
                            if (features.All(x => x.Name != feature.Name))
                            {
                                features.Add(feature);
                                hasNew = true;
                            }
                        }

                        if (hasNew)
                        {
                            currentDescriptor.Features = features;
                            shellDescriptorManager.UpdateShellDescriptor(currentDescriptor.SerialNumber, features, false);
                        }
                    }
                }
            }

            if (currentDescriptor != null && knownDescriptor.SerialNumber != currentDescriptor.SerialNumber)
            {
                Logger.Info("Newer descriptor obtained. Rebuilding shell container.");

                shellDescriptorCache.Store(settings.Name, currentDescriptor);
                blueprint = compositionStrategy.Compose(settings, currentDescriptor);
                shellScope.Dispose();
                shellScope = shellContainerFactory.CreateContainer(settings, blueprint);
            }

            if (currentDescriptor == null)
            {
                currentDescriptor = knownDescriptor;
            }

            return(new ShellContext
            {
                Settings = settings,
                Descriptor = currentDescriptor,
                Blueprint = blueprint,
                LifetimeScope = shellScope,
                Shell = shellScope.Resolve <ICMSShell>(),
            });
        }