/// <summary>
 /// 外壳设置保存成功之后。
 /// </summary>
 /// <param name="settings">外壳设置信息。</param>
 public void Saved(ShellSettings settings)
 {
     lock (NeedMigratorTenants)
     {
         if (!NeedMigratorTenants.Contains(settings.Name))
             NeedMigratorTenants.Add(settings.Name);
     }
 }
        public DataMigratorService(IEnumerable<IMigratorDataServicesProvider> migratorDataServicesProviders, IEnumerable<IMigration> migrations, ILifetimeScope lifetimeScope, ShellSettings shellSettings)
        {
            _migratorDataServicesProviders = migratorDataServicesProviders;
            _migrations = migrations;
            _lifetimeScope = lifetimeScope;
            _shellSettings = shellSettings;

            Logger = NullLogger.Instance;
        }
        /// <summary>
        /// 初始化一个表单授权服务。
        /// </summary>
        /// <param name="settings">租户设置。</param>
        /// <param name="clock">时钟服务。</param>
        /// <param name="httpContextAccessor">HttpContext访问器。</param>
        protected FormsAuthenticationServiceBase(ShellSettings settings, IClock clock, IHttpContextAccessor httpContextAccessor)
        {
            _settings = settings;
            _clock = clock;
            _httpContextAccessor = httpContextAccessor;

            Logger = NullLogger.Instance;
            ExpirationTimeSpan = TimeSpan.FromDays(30);
        }
 public DefaultRoutePublisher(RouteCollection routeCollection, ShellSettings shellSettings, IExtensionManager extensionManager, IWebWorkContextAccessor webWorkContextAccessor, IRunningShellTable runningShellTable, IEnumerable<IRoutePublisherEventHandler> routePublisherEventHandlers)
 {
     _routeCollection = routeCollection;
     _shellSettings = shellSettings;
     _extensionManager = extensionManager;
     _webWorkContextAccessor = webWorkContextAccessor;
     _runningShellTable = runningShellTable;
     _routePublisherEventHandlers = routePublisherEventHandlers;
 }
        public DefaultLocalizedStringManager(IVirtualPathProvider virtualPathProvider, IVirtualPathMonitor virtualPathMonitor, IExtensionManager extensionManager, ICacheManager cacheManager, ShellSettings shellSettings, ISignals signals)
        {
            _virtualPathProvider = virtualPathProvider;
            _virtualPathMonitor = virtualPathMonitor;
            _extensionManager = extensionManager;
            _cacheManager = cacheManager;
            _shellSettings = shellSettings;
            _signals = signals;

            Logger = NullLogger.Instance;
        }
Example #6
0
        public ShellRoute(RouteBase route, ShellSettings shellSettings, IWebWorkContextAccessor workContextAccessor, IRunningShellTable runningShellTable)
        {
            _route = route;
            _shellSettings = shellSettings;
            _runningShellTable = runningShellTable;
            _workContextAccessor = workContextAccessor;
            if (!string.IsNullOrEmpty(_shellSettings.GetRequestUrlPrefix()))
                _urlPrefix = new UrlPrefix(_shellSettings.GetRequestUrlPrefix());

            Area = route.GetAreaName();
        }
        /// <summary>
        /// 外壳设置保存成功之后。
        /// </summary>
        /// <param name="settings">外壳设置信息。</param>
        public void Saved(ShellSettings settings)
        {
            if (!DataMigratorsBuilderExtensions.StartingExecute)
                return;

            lock (NeedMigratorTenants)
            {
                if (!NeedMigratorTenants.Contains(settings.Name))
                    NeedMigratorTenants.Add(settings.Name);
            }
        }
        public DefaultShellDescriptorManager(IExtensionManager extensionManager, IEnumerable<IShellDescriptorManagerEventHandler> events, ShellSettings settings, IApplicationFolder applicationFolder)
        {
            _extensionManager = extensionManager;
            _events = events;
            _settings = settings;

            List.Init("~/App_Data/descriptors.dat", applicationFolder);

            var descriptor = List.OrderByDescending(i => i.SerialNumber).FirstOrDefault();
            _serialNumber = descriptor == null ? 0 : descriptor.SerialNumber;

            T = NullLocalizer.Instance;
        }
        private static RecordBlueprint BuildRecord(Type type, Feature feature, ShellSettings settings)
        {
            var extensionDescriptor = feature.Descriptor.Extension;
            var extensionName = extensionDescriptor.Id.Replace('.', '_');

            var dataTablePrefix = string.Empty;
            if (!string.IsNullOrEmpty(settings.GetDataTablePrefix()))
                dataTablePrefix = settings.GetDataTablePrefix() + "_";

            return new RecordBlueprint
            {
                Type = type,
                Feature = feature,
                TableName = dataTablePrefix + extensionName + '_' + type.Name,
            };
        }
        /// <summary>
        /// 添加。
        /// </summary>
        /// <param name="settings">外壳设置。</param>
        public void Add(ShellSettings settings)
        {
            _lock.EnterWriteLock();
            try
            {
                _shells = _shells
                    .Where(s => s.Name != settings.Name)
                    .Concat(new[] { settings })
                    .ToArray();

                Organize();
            }
            finally
            {
                _lock.ExitWriteLock();
            }
        }
Example #11
0
        public void ActivateShell(ShellSettings settings)
        {
            Logger.Debug("准备激活外壳: " + settings.Name);

            //寻找相关的外壳上下文
            var shellContext = _shellContexts.FirstOrDefault(c => c.Settings.Name == settings.Name);

            if (shellContext == null && settings.State == TenantState.Disabled)
                return;

            if (shellContext == null || settings.State == TenantState.Uninitialized)
            {
                //创建外壳
                var context = CreateShellContext(settings);

                //激活外壳
                ActivateShell(context);
            }
            //租户被禁用则终止外壳
            else if (settings.State == TenantState.Disabled)
            {
                shellContext.Shell.Terminate();
                shellContext.Container.Dispose();
                _runningShellTable.Remove(settings);

                _shellContexts = _shellContexts.Where(shell => shell.Settings.Name != settings.Name);
            }
            //重新加载因为外壳设置被变更的外壳
            else
            {
                //释放之前的外壳上下文
                shellContext.Shell.Terminate();
                shellContext.Container.Dispose();

                var context = _shellContextFactory.CreateShellContext(settings);

                //激活并注册已修改的外壳上下文
                _shellContexts = _shellContexts.Where(shell => shell.Settings.Name != settings.Name).Union(new[] { context });

                context.Shell.Activate();
                _runningShellTable.Update(settings);
            }
        }
        /// <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>(),
            };
        }
Example #13
0
        /// <summary>
        /// 执行命令。
        /// </summary>
        /// <param name="context">命令执行上下文。</param>
        public override void Execute(CommandExecuteContext context)
        {
            var settings = SettingsManager.LoadSettings().FirstOrDefault(i => string.Equals(i.Name, TenantName, StringComparison.OrdinalIgnoreCase));
            var isAdd = settings == null;
            if (settings != null && !Quiet)
            {
                context.WriteLine("已经存在名称为 '{0}' 的租户,确定要替换吗?\t输入'Y'继续执行,输入其他则终止执行。", TenantName);
                var t = context.Read("y");
                if (!t.Equals("y", StringComparison.OrdinalIgnoreCase))
                    return;
            }
            else
                settings = new ShellSettings();

            if (List != null)
            {
                foreach (var temp in List.Where(i => !string.IsNullOrWhiteSpace(i)))
                {
                    var index = temp.IndexOf("=", StringComparison.Ordinal);
                    if (index == -1)
                        continue;

                    var key = temp.Substring(0, index).Escape();
                    var value = temp.Substring(index);

                    if (value.StartsWith("="))
                        value = value.Remove(0, 1);

                    if (string.IsNullOrWhiteSpace(value))
                        continue;

                    value = value.Escape();
                    settings[key] = value.Escape();
                }
            }

            settings.Name = TenantName;
            settings.State = State;
            SettingsManager.SaveSettings(settings);

            context.WriteLine("{0}租户 '{1}' 成功。", isAdd ? "添加" : "修改", TenantName);
        }
Example #14
0
        /// <summary>
        /// 创建一个独立的环境。
        /// </summary>
        /// <param name="shellSettings">外壳设置。</param>
        /// <returns>工作上下文范围。</returns>
        IWorkContextScope IHost.CreateStandaloneEnvironment(ShellSettings shellSettings)
        {
            Logger.Debug("为租户 {0} 创建独立的环境。", shellSettings.Name);

            MonitorExtensions();
            BuildCurrent();
            var shellContext = CreateShellContext(shellSettings);
            return shellContext.Container.CreateWorkContextScope();
        }
Example #15
0
 /// <summary>
 /// 获取一个外壳上下文。
 /// </summary>
 /// <param name="shellSettings">外壳设置。</param>
 /// <returns>外壳上下文。</returns>
 public ShellContext GetShellContext(ShellSettings shellSettings)
 {
     return BuildCurrent().SingleOrDefault(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name, StringComparison.OrdinalIgnoreCase));
 }
Example #16
0
 private ShellContext CreateShellContext(ShellSettings settings)
 {
     Logger.Debug("为租户 {0} 创建外壳上下文", settings.Name);
     return _shellContextFactory.CreateShellContext(settings);
 }
Example #17
0
        /// <summary>
        /// 外壳设置保存成功之后。
        /// </summary>
        /// <param name="settings">外壳设置信息。</param>
        void IShellSettingsManagerEventHandler.Saved(ShellSettings settings)
        {
            Logger.Debug("外壳 {0} 被保存 ", settings.Name);

            if (settings.State == TenantState.Invalid)
                return;
            if (_tenantsToRestart.GetState().Any(t => t.Name.Equals(settings.Name)))
                return;
            Logger.Debug("标识租户: {0} {1} 需要重启", settings.Name, settings.State);
            _tenantsToRestart.GetState().Add(settings);
        }
 /// <summary>
 /// 外壳设置保存成功之后。
 /// </summary>
 /// <param name="settings">外壳设置信息。</param>
 public void Saved(ShellSettings settings)
 {
     _eventIsRun = true;
 }
 public TenantThemeSelector(ShellSettings settings)
 {
     _settings = settings;
 }
        public EntityFrameworkDbContextFactory(IServiceTypeHarvester serviceTypeHarvester, IEnumerable<IEntityFrameworkDataServicesProvider> dataServicesProviders, IEnumerable<IMapping> mappings, ShellBlueprint shellBlueprint)
        {
            _serviceTypeHarvester = serviceTypeHarvester;
            _dataServicesProviders = dataServicesProviders;
            _mappings = mappings;
            _recordBlueprints = shellBlueprint.GetRecords();
            _shellSettings = shellBlueprint.Settings;

            Logger = NullLogger.Instance;
        }
        private DbCompiledModel GetDbCompiledModel(ShellSettings shellSettings)
        {
            if (DbCompiledModelCacheDictionary.ContainsKey(shellSettings.Name))
                return DbCompiledModelCacheDictionary[shellSettings.Name];

            var records = _recordBlueprints.ToArray();
            var modelBuilder = new DbModelBuilder();

            //设置数据库架构名称。
            //            modelBuilder.HasDefaultSchema(shellSettings.Name);

            //将记录类型添加至DbContext。
            foreach (var recordBlueprint in records)
                Entity(recordBlueprint.Type, modelBuilder);

            //默认配置信息。
            modelBuilder.Types().Configure(config =>
            {
                var record = records.FirstOrDefault(i => i.Type == config.ClrType);
                if (record == null)
                    return;
                config.ToTable(record.TableName);
            });

            //应用约定。
            modelBuilder.Conventions.Add(GetConventions());

            var dataServiceProvider = GetDataServicesProvider(shellSettings);
            var connectionString = shellSettings.GetDataConnectionString();

            string providerManifestToken;

            using (var connection = dataServiceProvider.CreateConnection(connectionString))
                providerManifestToken = dataServiceProvider.Instance.GetProviderManifestToken(connection);

            var dbProviderInfo = new DbProviderInfo(dataServiceProvider.ProviderInvariantName, providerManifestToken);
            var dbModel = modelBuilder.Build(dbProviderInfo);

            return dbModel.Compile();
        }
 public DefaultTenantService(ShellSettings shellSettings, ICacheManager cacheManager)
 {
     _shellSettings = shellSettings;
     _cacheManager = cacheManager;
 }
Example #23
0
 /// <summary>
 /// 获取一个外壳上下文。
 /// </summary>
 /// <param name="shellSettings">外壳设置。</param>
 /// <returns>外壳上下文。</returns>
 public ShellContext GetShellContext(ShellSettings shellSettings)
 {
     return BuildCurrent().SingleOrDefault(shellContext => shellContext.Settings.Name.Equals(shellSettings.Name));
 }
 public DefaultEncryptionService(ShellSettings shellSettings)
 {
     _shellSettings = shellSettings;
 }
Example #25
0
 /// <summary>
 /// 初始化一个新的外壳设置。
 /// </summary>
 /// <param name="settings">外壳设置。</param>
 public ShellSettings(ShellSettings settings)
     : this()
 {
     foreach (var item in settings.Keys)
         this[item] = settings[item];
 }
        private IEntityFrameworkDataServicesProvider GetDataServicesProvider(ShellSettings shellSettings)
        {
            var providerName = shellSettings.GetDataProvider();

            if (string.IsNullOrWhiteSpace(providerName))
                throw new ArgumentException("因为数据服务提供名称为空,所以无法确定数据服务提供者。");

            var provider = _dataServicesProviders.FirstOrDefault(
                p => string.Equals(p.ProviderName, providerName, StringComparison.OrdinalIgnoreCase));

            if (provider == null)
                throw new NotSupportedException(string.Format("找不到名称为:{0}的数据服务提供程序。", providerName));

            return provider;
        }
 /// <summary>
 /// 初始化一个表单授权服务。
 /// </summary>
 /// <param name="settings">租户设置。</param><param name="clock">时钟服务。</param><param name="httpContextAccessor">HttpContext访问器。</param>
 public FormsAuthenticationService(ShellSettings settings, IClock clock, IHttpContextAccessor httpContextAccessor)
     : base(settings, clock, httpContextAccessor)
 {
 }
 public DbConnectionFactory(ShellSettings shellSettings, IEnumerable<IDbConnectionProvider> providers)
 {
     _shellSettings = shellSettings;
     _providers = providers;
 }
        /// <summary>
        /// 创建一个外壳容器。
        /// </summary>
        /// <param name="settings">外壳设置。</param>
        /// <param name="blueprint">外壳蓝图。</param>
        /// <returns>外壳容器。</returns>
        public ILifetimeScope CreateContainer(ShellSettings settings, ShellBlueprint blueprint)
        {
            var intermediateScope = _lifetimeScope.BeginLifetimeScope(
                builder =>
                {
                    //TODO:CollectionOrderModule、CacheModule 等Module是公共的,需要验证 Root 范围注册了子级生命范围是否生效,如果生效则在外壳容器中忽略掉这些Module
                    foreach (var item in blueprint.Dependencies.Where(t => typeof(IModule).IsAssignableFrom(t.Type)))
                    {
                        RegisterType(builder, item)
                            .Keyed<IModule>(item.Type)
                            .InstancePerDependency();
                    }
                });

            return intermediateScope.BeginLifetimeScope(
                "shell",
                builder =>
                {
                    builder.Register(ctx => settings);
                    builder.Register(ctx => blueprint.Descriptor);
                    builder.Register(ctx => blueprint);

                    var moduleIndex = intermediateScope.Resolve<IIndex<Type, IModule>>();
                    foreach (var item in blueprint.Dependencies.Where(t => typeof(IModule).IsAssignableFrom(t.Type)))
                    {
                        builder.RegisterModule(moduleIndex[item.Type]);
                    }

                    foreach (var item in blueprint.Dependencies.Where(t => typeof(IDependency).IsAssignableFrom(t.Type)))
                    {
                        var registration = RegisterType(builder, item)
                            .InstancePerLifetimeScope();

                        foreach (var interfaceType in item.Type.GetInterfaces()
                            .Where(itf => typeof(IDependency).IsAssignableFrom(itf)
                                      && !typeof(IEventHandler).IsAssignableFrom(itf)))
                        {
                            registration = registration.As(interfaceType);
                            if (typeof(ISingletonDependency).IsAssignableFrom(interfaceType))
                            {
                                registration = registration.InstancePerMatchingLifetimeScope("shell");
                            }
                            else if (typeof(IUnitOfWorkDependency).IsAssignableFrom(interfaceType))
                            {
                                registration = registration.InstancePerMatchingLifetimeScope("work");
                            }
                            else if (typeof(ITransientDependency).IsAssignableFrom(interfaceType))
                            {
                                registration = registration.InstancePerDependency();
                            }
                        }

                        if (!typeof(IEventHandler).IsAssignableFrom(item.Type))
                            continue;
                        var interfaces = item.Type.GetInterfaces();
                        foreach (var interfaceType in interfaces)
                        {
                            if (interfaceType.GetInterface(typeof(IEventHandler).Name) != null)
                            {
                                registration = registration.Named<IEventHandler>(interfaceType.Name);
                            }
                        }
                    }

                    _shellContainerRegistrationses.Invoke(i => i.Registrations(builder, blueprint), NullLogger.Instance);
                });
        }
        private void Organize()
        {
            var qualified =
                _shells.Where(x => !string.IsNullOrEmpty(x.GetRequestUrlHost()) || !string.IsNullOrEmpty(x.GetRequestUrlPrefix()));

            var unqualified = _shells
                .Where(x => string.IsNullOrEmpty(x.GetRequestUrlHost()) && string.IsNullOrEmpty(x.GetRequestUrlPrefix()))
                .ToList();

            _shellsByHost = qualified
                .SelectMany(s => s.GetRequestUrlHost() == null || s.GetRequestUrlHost().IndexOf(',') == -1 ? new[] { s } :
                    s.GetRequestUrlHost().Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries)
                     .Select(h =>
                     {
                         var settings = new ShellSettings(s);
                         settings.SetRequestUrlHost(h);
                         return settings;
                     }))
                .GroupBy(s => s.GetRequestUrlHost() ?? string.Empty)
                .OrderByDescending(g => g.Key.Length)
                .ToDictionary(x => x.Key, x => x.AsEnumerable(), StringComparer.OrdinalIgnoreCase);

            if (unqualified.Count() == 1)
            {
                _fallback = unqualified.Single();
            }
            else if (unqualified.Any())
            {
                _fallback = unqualified.SingleOrDefault(x => x.Name == ShellSettings.DefaultName);
            }
            else
            {
                _fallback = null;
            }

            _shellsByHostAndPrefix.Clear();
        }