コード例 #1
0
        /// <summary>
        /// 使用 Redis 缓存服务(将以 Redis 缓存实现 <see cref="ICacheManager"/> 接口,默认连接配置节为 Schubert:Redis。)。
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="setup"> Redis 缓存的配置安装方法。</param>
        /// <returns></returns>
        public static SchubertServicesBuilder AddRedisCache(this SchubertServicesBuilder builder, Action <SchubertRedisOptions> setup = null)
        {
            var configuration = builder.Configuration.GetSection("Schubert:Redis") as IConfiguration ?? new ConfigurationBuilder().Build();

            builder.ServiceCollection.Configure <SchubertRedisOptions>(configuration);

            SchubertRedisOptions options = new SchubertRedisOptions();
            var redisSetup = new ConfigureFromConfigurationOptions <SchubertRedisOptions>(configuration);

            redisSetup.Configure(options);
            if (setup != null)
            {
                setup(options);
                builder.ServiceCollection.Configure(setup);
            }

            builder.ServiceCollection.AddSmart(ServiceDescriber.Singleton <ICacheManager, RedisCacheManager>(SmartOptions.Replace));
            if (builder.AddedModules.Add(_module))
            {
                builder.ServiceCollection.AddSmart(ServiceDescriber.Singleton <IRedisCacheSerializer, JsonNetSerializer>(SmartOptions.Append));
            }

            if (options.ConnectionString.IsNullOrWhiteSpace())
            {
                throw new SchubertException("必须为 RedisCacheManager 指定连接字符串,可以通过 Schubert:Redis:ConnectionString 配置节配置。");
            }

            return(builder);
        }
コード例 #2
0
        /// <summary>
        /// 添加以 Dapper 作为持久化的数据层特性。
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="setup"></param>
        /// <returns></returns>
        public static SchubertServicesBuilder AddDapperDataFeature(this SchubertServicesBuilder builder, Action <DapperDataFeatureBuilder> setup = null)
        {
            DapperDatabaseOptions dbOptions = new DapperDatabaseOptions();

            if (builder.AddedModules.Add(_module))
            {
                //修改dapper的默认映射规则,让其支持下划线列名到C#实体驼峰命名属性
                Dapper.DefaultTypeMap.MatchNamesWithUnderscores = true;

                var configuration = builder.Configuration.GetSection("Schubert:Data") as IConfiguration ?? new ConfigurationBuilder().Build();

                builder.ServiceCollection.Configure <DapperDatabaseOptions>(configuration);

                var schubertDataSetup = new ConfigureFromConfigurationOptions <DapperDatabaseOptions>(configuration);
                schubertDataSetup.Configure(dbOptions);
            }

            DapperDataFeatureBuilder featureBuilder = new DapperDataFeatureBuilder(dbOptions);

            setup?.Invoke(featureBuilder);


            featureBuilder.Build();
            builder.ServiceCollection.Configure(featureBuilder.Configure);

            builder.ServiceCollection.AddSmart(DapperServices.GetServices(dbOptions));
            return(builder);
        }
コード例 #3
0
        public static SchubertServicesBuilder AddEntityFrameworkFeature(this SchubertServicesBuilder builder, Action <DbBuilder> setup = null)
        {
            DbOptions options = new DbOptions();

            if (builder.AddedModules.Add(_module))
            {
                var configuration = builder.Configuration.GetSection("Schubert:Data") as IConfiguration ?? new ConfigurationBuilder().Build();
                builder.ServiceCollection.Configure <DbOptions>(configuration);

                var schubertDataSetup = new ConfigureFromConfigurationOptions <DbOptions>(configuration);
                schubertDataSetup.Configure(options);
            }


            DbBuilder dbBuilder = new DbBuilder();

            if (setup != null)
            {
                setup(dbBuilder);
                if (dbBuilder.Setup != null)
                {
                    dbBuilder.Setup(options);
                    builder.ServiceCollection.Configure(dbBuilder.Setup);
                }
            }

            options.DbContextSettings = dbBuilder.DbSettings;
            builder.ServiceCollection.Configure <DbOptions>(dbOp =>
            {
                dbOp.DbContextSettings.AddRange(dbBuilder.DbSettings, true);
            });
            _dbConnectionMappings.AddRange(dbBuilder.DbContexts, true);

            if (dbBuilder.ShellDbAdded)
            {
                builder.ServiceCollection.AddSmart(ServiceDescriber.Scoped <IRepository <ShellDescriptorRecord>, Repository <ShellDescriptorRecord, ShellDescriptorDbContext> >());
                builder.ServiceCollection.AddSmart(ServiceDescriber.Scoped <IRepository <SettingRecord>, Repository <SettingRecord, ShellDescriptorDbContext> >());
                builder.ServiceCollection.AddSmart(ServiceDescriber.Scoped <IShellDescriptorManager, ShellDescriptorManager>());
            }

            builder.ServiceCollection.AddSmart(EntityFrameworkServices.GetServices(options));


            foreach (var action in dbBuilder.DbConfigurings.Values)
            {
                action(builder.ServiceCollection);
            }

            builder.ServiceCollection.AddSmart(ServiceDescriber.Scoped(
                                                   s =>
            {
                IOptions <DbOptions> dbOps = s.GetRequiredService <IOptions <DbOptions> >();
                return(new DbContextResources(s, dbBuilder.DefaultDbConnectionName, _dbConnectionMappings));
            },
                                                   SmartOptions.Replace));

            builder.ServiceCollection.TryAddScoped <IDatabaseContext>(s => s.GetRequiredService <DbContextResources>());

            return(builder);
        }
コード例 #4
0
        /// <summary>
        /// 向服务集合中添加 SchubertFramework 的依赖服务。
        /// </summary>
        /// <param name="services"></param>
        /// <param name="configuration">应用程序配置对象。</param>
        /// <param name="setupAction">SchubertFramework 安装选项。</param>
        /// <param name="shellCreationSetup">配置 Shell 环境,该操作作用域仅为 Shell 创建过程。</param>
        public static void AddSchubertFramework(this IServiceCollection services, IConfiguration configuration,
                                                Action <SchubertServicesBuilder> setupAction   = null,
                                                Action <ShellCreationScope> shellCreationSetup = null)
        {
            AddVariables(configuration);

            IConfiguration c = (configuration.GetSection("Schubert") as IConfiguration) ?? new ConfigurationBuilder().Build();

            Console.OutputEncoding = System.Text.Encoding.UTF8;
            Guard.ArgumentNotNull(configuration, nameof(configuration));

            SchubertEngine.Current.ApplicationName    = c.GetSection(nameof(SchubertOptions.AppSystemName))?.Value.IfNullOrWhiteSpace(String.Empty);
            SchubertEngine.Current.GroupName          = c.GetSection(nameof(SchubertOptions.Group))?.Value.IfNullOrWhiteSpace(String.Empty);
            SchubertEngine.Current.ApplicationVersion = c.GetSection(nameof(SchubertOptions.Version))?.Value.IfNullOrWhiteSpace("0.0.0");
            services.Configure <MemoryCacheOptions>(o => o.ExpirationScanFrequency = TimeSpan.FromMinutes(3));
            //刷新和ExpirationScanFrequency的设置没有关系
            services.Configure <SchubertOptions>(c);

            var networkConfiguration = (configuration.GetSection("Schubert:Network") as IConfiguration) ?? new ConfigurationBuilder().Build();

            services.Configure <NetworkOptions>(networkConfiguration);

            var builder = new SchubertServicesBuilder(services, configuration);

            setupAction?.Invoke(builder);

            InitShell(builder, shellCreationSetup);
        }
コード例 #5
0
        public override void ConfigureServices(SchubertServicesBuilder servicesBuilder, SchubertWebOptions webOptions)
        {
            servicesBuilder.ServiceCollection.Configure <MvcOptions>(options =>
            {
                options.ModelMetadataDetailsProviders.Add(new FluentValidationMetadataProvider());
                options.ModelValidatorProviders.Add(new FluentValidationModelValidatorProvider());
            });

            servicesBuilder.ServiceCollection.AddTransient <IConfigureOptions <MvcViewOptions>, LabijieMvcViewOptionsSetup>();
        }
コード例 #6
0
 /// <summary>
 /// 使用 Schubert 提供的缓存来实现 asp.net 框架中的缓存(<see cref="IDistributedCache"/>)提供程序。
 /// </summary>
 /// <param name="collection"></param>
 /// <param name="regionName">用来存储 asp.net 缓存数据的分区。</param>
 public static void AddCacheForAspNet(this SchubertServicesBuilder collection, string regionName = "aspnet")
 {
     collection.ServiceCollection.AddSmart(new SmartServiceDescriptor(typeof(IDistributedCache), serviceProvider =>
     {
         var manager = serviceProvider.GetRequiredService <ICacheManager>();
         return(new DistributedCacheAdapter(manager, regionName));
     }, ServiceLifetime.Transient)
     {
         Options = SmartOptions.TryAdd
     });
 }
コード例 #7
0
        public override void ConfigureServices(SchubertServicesBuilder servicesBuilder, SchubertWebOptions options)
        {
            var identitySvcdescriptor = ServiceDescriber.Scoped <IIdentityService, TIdentityService>();

            servicesBuilder.ServiceCollection.AddSmart(identitySvcdescriptor);

            servicesBuilder.ServiceCollection
            .AddIdentity <TUser, TRole>(iop => _configure?.Invoke(iop))
            .AddDefaultTokenProviders()
            .AddDapperStores <TUser, TRole>();
        }
コード例 #8
0
ファイル: SwiftyExtensions.cs プロジェクト: tinytian/Schubert
        /// <summary>
        /// 向服务容器中添加 Swifty (基于 Thrift 的 RPC)服务。
        /// 可以使用 <see cref="SwiftyOptions.EnableFeatures"/> 控制是否启用客户端/服务端功能。
        /// </summary>
        /// <param name="builder"></param>
        /// <param name="setupAction">对 Swifty 进行配置的委托。</param>
        public static void AddSwifty(this SchubertServicesBuilder builder, Action <SwiftyOptions> setupAction = null)
        {
            SwiftyOptions touchOptions = AddSwiftyOptions(builder, setupAction);

            //启动服务端。
            if (touchOptions.EnableFeatures.HasFlag(SwiftyFeatures.Server))
            {
                AddSwiftyServer();
            }

            if (touchOptions.EnableFeatures.HasFlag(SwiftyFeatures.Client) /*&& !touchOptions.Client.ExploringAssemblies.IsNullOrEmpty()*/)
            {
                AddSwiftyClient(touchOptions);
            }
        }
コード例 #9
0
        private static void AddMvc(SchubertServicesBuilder services, SchubertWebBuilder featureBuilder, SchubertWebOptions options)
        {
            Action <MvcOptions> configure = mvc =>
            {
                if (!options.GlobalRoutePrefix.IsNullOrWhiteSpace())
                {
                    mvc.Conventions.Insert(0, new RoutePrefixConvention(new RouteAttribute(options.GlobalRoutePrefix.Trim())));
                }
            };

            switch (options.MvcFeatures)
            {
            case MvcFeatures.Full:
                var mvcBuilder = services.ServiceCollection.AddMvc(configure);
                featureBuilder.MvcSetup?.Invoke(mvcBuilder);
                mvcBuilder.AddJsonOptions(json => json.SerializerSettings.ContractResolver = GetContractResolver(options.JsonCaseStyle, options.JsonResolver))
                .AddRazorOptions(rveo =>
                {
                    rveo.FileProviders.Insert(0, new ModuleFileProvider(rveo.FileProviders.FirstOrDefault()));
                    rveo.ViewLocationExpanders.Insert(0, new ModuleViewLocationExpander());
                });
                //services.ServiceCollection.AddAntiforgery();
                break;

            case MvcFeatures.Core:
                var coreBuilder = services.ServiceCollection.AddMvcCore(configure);
                featureBuilder.MvcCoreSetup?.Invoke(coreBuilder);
                break;

            case MvcFeatures.Api:
                var apiBuilder = services.ServiceCollection.AddMvcCore(configure);
                featureBuilder.MvcCoreSetup?.Invoke(apiBuilder);
                apiBuilder.AddApiExplorer()
                .AddAuthorization()
                .AddFormatterMappings()
                .AddJsonFormatters(settings => settings.ContractResolver = GetContractResolver(options.JsonCaseStyle, options.JsonResolver))
                .AddDataAnnotations()
                .AddCors();
                featureBuilder.AddWebApiConventions();
                break;

            default:
                return;
            }
        }
コード例 #10
0
        /// <summary>
        /// 添加任务调度组件。
        /// </summary>
        /// <param name="builder"><see cref="SchubertServicesBuilder"/> 对象。</param>
        /// <param name="setup">用于配置调度组件的方法。</param>
        /// <returns></returns>
        public static SchubertServicesBuilder AddJobScheduling(this SchubertServicesBuilder builder, Action <SchedulingOptions> setup = null)
        {
            if (builder.AddedModules.Add(_module))
            {
                builder.ServiceCollection.AddSmart(ServiceDescriber.Singleton(typeof(IWorkContextProvider), typeof(JobWorkContextProvider), SmartOptions.Append));
            }
            builder.ServiceCollection.AddSmart(ServiceDescriber.Singleton(typeof(ISchedulingServer), typeof(QuartzSchedulingServer), SmartOptions.TryAdd));

            var schedulingConfiguration = builder.Configuration.GetSection("Schubert:Scheduling");

            builder.ServiceCollection.Configure <SchedulingOptions>(schedulingConfiguration);
            if (setup != null)
            {
                builder.ServiceCollection.Configure(setup);
            }
            ShellEvents.EngineStarted -= ShellEvents_OnEngineStarted;
            ShellEvents.EngineStarted += ShellEvents_OnEngineStarted;
            return(builder);
        }
コード例 #11
0
ファイル: SwiftyExtensions.cs プロジェクト: tinytian/Schubert
        private static SwiftyOptions AddSwiftyOptions(SchubertServicesBuilder builder, Action <SwiftyOptions> setupAction)
        {
            SwiftyOptions touchOptions = new SwiftyOptions();

            var configuration = builder.Configuration.GetSection("Schubert:Swifty") as IConfiguration ?? new ConfigurationBuilder().Build();

            var schubertDataSetup = new ConfigureFromConfigurationOptions <SwiftyOptions>(configuration);

            builder.ServiceCollection.Configure <SwiftyOptions>(configuration);

            schubertDataSetup.Configure(touchOptions);

            if (setupAction != null)
            {
                builder.ServiceCollection.Configure(setupAction);
                setupAction(touchOptions);
            }
            builder.ServiceCollection.AddSmart(SwiftyServices.GetServices());
            return(touchOptions);
        }
コード例 #12
0
 public SchubertWebBuilder(SchubertServicesBuilder builder)
 {
     _builder = builder;
 }
コード例 #13
0
 protected internal abstract void ConfigureServices(SchubertServicesBuilder builder);
コード例 #14
0
        private static void InitShell(SchubertServicesBuilder schubertBuilder, Action <ShellCreationScope> setup)
        {
            ShellCreationScope shellScope = new ShellCreationScope();

            setup?.Invoke(shellScope);

            var builder = schubertBuilder.ServiceCollection.FillToOther();

            builder.AddSmart(SchubertServices.GetServices(schubertBuilder.Configuration));
            builder.AddLogging(lb =>
            {
                shellScope.LoggingConfigure?.Invoke(lb);
            });

            var scopeFactory = builder.BuildServiceProvider().GetRequiredService <IServiceScopeFactory>();

            using (IServiceScope scope = scopeFactory.CreateScope())
            {
                IServiceProvider provider = scope.ServiceProvider;
                var shellLogger           = provider.GetRequiredService <ILoggerFactory>().CreateLogger("Schubert");

                shellLogger.WriteInformation("开始加载 Shell。");

                var sw = Stopwatch.StartNew();
                SchubertEngine.Current.LoadEnvironment(provider);
                var factory = provider.GetRequiredService <IShellContextFactory>();
                var context = factory.CreateShellContext();

                AddConfiguredOptions(schubertBuilder.ServiceCollection, schubertBuilder.Configuration, context);

                //微软框架依然存在解决日志组件创建后的销毁问题,只能通过移除日志来达到清理目的。
                schubertBuilder.ServiceCollection.Remove(sd => sd.ServiceType.Equals(typeof(ILoggerFactory)));
                schubertBuilder.ServiceCollection.AddLogging(b => b.AddConfiguration(schubertBuilder.Configuration.GetSection("Logging")));

                schubertBuilder.ServiceCollection.AddSingleton(context);
                schubertBuilder.ServiceCollection.AddSmart(context.Services);
                schubertBuilder.ServiceCollection.AddSmart(SchubertServices.GetServices(schubertBuilder.Configuration));

                SchubertEngine.Current.ShellCreated = true;

                IOptions <SchubertOptions> schubertOptions = provider.GetRequiredService <IOptions <SchubertOptions> >();

                context.RegisteredServices = builder;
                ShellEvents.NotifyShellInitialized(schubertOptions.Value, context);
                sw.Stop();


                var table = new Tuple <int, int, int, int, String>(
                    context.Blueprint.Modules.Count(),
                    context.Blueprint.Controllers.Count(),
                    context.Blueprint.Dependencies.Count(),
                    context.Blueprint.DependencyDescribers.Count(),
                    context.Blueprint.Modules.ToArrayString(System.Environment.NewLine));

                StringBuilder info = new StringBuilder();
                info.AppendLine(@"
 ________  ________  ___  ___  ___  ___  ________  _______   ________  _________   
|\   ____\|\   ____\|\  \|\  \|\  \|\  \|\   __  \|\  ___ \ |\   __  \|\___   ___\ 
\ \  \___|\ \  \___|\ \  \\\  \ \  \\\  \ \  \|\ /\ \   __/|\ \  \|\  \|___ \  \_| 
 \ \_____  \ \  \    \ \   __  \ \  \\\  \ \   __  \ \  \_|/_\ \   _  _\   \ \  \  
  \|____|\  \ \  \____\ \  \ \  \ \  \\\  \ \  \|\  \ \  \_|\ \ \  \\  \|   \ \  \ 
    ____\_\  \ \_______\ \__\ \__\ \_______\ \_______\ \_______\ \__\\ _\    \ \__\
   |\_________\|_______|\|__|\|__|\|_______|\|_______|\|_______|\|__|\|__|    \|__|
   \|_________|                                                                         
                                                                                   ");

                info.AppendLine($"Shell 加载完成,Schubert Version: {typeof(SchubertException).GetTypeInfo().Assembly.GetName().Version.ToString()} ({sw.ElapsedMilliseconds} ms)。");
                info.AppendLine("  ");
                info.AppendLine((new Tuple <int, int, int, int, String>[] { table }).ToStringTable(new String[] { "modules", "controllers", "dependencies", "describers", "moduleList" },
                                                                                                   t => t.Item1, t => t.Item2, t => t.Item3, t => t.Item4, t => t.Item5));
                info.AppendLine("   ");
                info.Append(context.Blueprint.Dependencies.GroupBy(d => d.Feature.Descriptor.ModuleName, d => (ShellBlueprintDependencyItem)d).ToStringTable(
                                new string[] { "module", "dependencies", "internfaces", "lifetime" },
                                f => f.Key,
                                d => d.SelectMany(t => CreateArray(t.Type.Name, t.Interfaces.Count)).ToArrayString(System.Environment.NewLine),
                                d => d.SelectMany(t => t.Interfaces).Select(i => i.Item1.Name).ToArrayString(System.Environment.NewLine),
                                d => d.SelectMany(t => t.Interfaces).Select(i => i.Item2.ToString().ToLower()).ToArrayString(System.Environment.NewLine)));
                info.AppendLine("   ");

                shellLogger.WriteInformation(info.ToString());
            }
        }
コード例 #15
0
ファイル: WebStarter.cs プロジェクト: tinytian/Schubert
 public abstract void ConfigureServices(SchubertServicesBuilder servicesBuilder, SchubertWebOptions options);
コード例 #16
0
        /// <summary>
        /// 启用Schubert 框架的 Web 特性。
        /// </summary>
        /// <param name="services"></param>
        /// <param name="setup">加入 Mvc 支持。</param>
        /// <returns></returns>
        public static SchubertServicesBuilder AddWebFeature(this SchubertServicesBuilder services, Action <SchubertWebBuilder> setup = null)
        {
            SchubertWebOptions options = new SchubertWebOptions();
            bool firstInvoke           = true;

            if ((firstInvoke = services.AddedModules.Add(_module)))
            {
                IConfiguration configuration = services.Configuration.GetSection("Schubert:Web") as IConfiguration ?? new ConfigurationBuilder().Build();

                services.ServiceCollection.Configure <SchubertWebOptions>(configuration);

                var schubertWebSetup = new SchubertWebOptionsSetup(configuration);
                schubertWebSetup.Configure(options);
            }

            _webBuilder = new SchubertWebBuilder(services);
            setup?.Invoke(_webBuilder);


            if (_webBuilder.FeatureSetup != null)
            {
                services.ServiceCollection.Configure(setup);
            }
            _webBuilder.FeatureSetup?.Invoke(options);
            services.ServiceCollection.AddDataProtection();

            services.ServiceCollection.AddLocalization();
            services.ServiceCollection.Replace(ServiceDescriptor.Singleton <IStringLocalizerFactory, SchubertStringLocalizerFactory>());
            services.ServiceCollection.TryAddSingleton <IMemoryCache>(s => LocalCache.InnerCache);
            services.AddCacheForAspNet();

            var cookieSetup = _webBuilder.CookieSetup;

            services.ServiceCollection.ConfigureApplicationCookie(o =>
            {
                o.LoginPath           = "/Login";
                o.LogoutPath          = "/LogOff";
                o.Cookie.HttpOnly     = true;
                o.Cookie.SecurePolicy = CookieSecurePolicy.SameAsRequest;
                cookieSetup?.Invoke(o);
            });

            var authenticationBuilder = services.ServiceCollection.AddAuthentication();

            if (options.UseCookieAuth)
            {
                authenticationBuilder.AddCookie();
            }
            if (options.UseSession)
            {
                services.ServiceCollection.AddSession(sop =>
                {
                    sop.IdleTimeout = TimeSpan.FromMinutes(options.SessionTimeoutMinutes);
                });
            }

            services.ServiceCollection.AddSmart(SchubertWebServices.GetServices(options, firstInvoke));

            foreach (var s in _webBuilder.WebStarters)
            {
                s.ConfigureServices(services, options);
            }

            AddMvc(services, _webBuilder, options);

            return(services);
        }