ãšã³ããªãŒ
ãããžã§ã¯ãããŒã ãæåãå°œããããšããã«èšã䟡å€ããããŸãã ã»ãŒ1æ¥ã§ãå¹³åçãªç 究ãããžã§ã¯ããæ°åã®ãµãŒãã¹ã§æ°ããçŸå®ã«é©å¿ãããããšãã§ããŸããã
è²æž¡ããã®å©çã¯äœã§ããïŒ ééããªã-客芳çã«å¿çãšã¯ãšãªåŠçã®é床ãäžããŸããã åã ã®æ¹æ³ã«ãããå¿çæéã¯3åæžå°ããŸããã å¹³åããŠãçç£æ§ã®äŒžã³ã¯30ïŒ ã§ããã ãã¡ãããäž»ãªãã€ã³ãã¯ãSystem.Webã©ã€ãã©ãªãããã³äžè¬ã«ãã¡ã€ã³ã®ServiceStackãããžã§ã¯ãã®ããŒã¹ã§ããASP.NETãµãã·ã¹ãã å šäœã®äžè¶³ã«ãããªãŒããŒããããæžå°ããããšã§ãã
ã³ã¢ã©ã€ãã©ãª
äœæè ã¯ãã¡ã€ã³ããã±ãŒãžã§çŽæ¥.NET CoreããµããŒããããæ°ããããŒãžã§ã³1.0- *ïŒå·çæç¹ã§1.0.25ïŒã§åå¥ã®ããã±ãŒãžã»ããããªãªãŒã¹ããŸããã
ããã±ãŒãžã®ã»ããã¯éåžžã«åºç¯å²ã§ãïŒ
- ServiceStack.Text.Core
- ServiceStack.Interfaces.Core
- ServiceStack.Client.Core
- ServiceStack.HttpClient.Core
- ServiceStack.Common.Core
- ServiceStack.Redis.Core
- ServiceStack.OrmLite.Core
- ServiceStack.OrmLite.Sqlite.Core
- ServiceStack.OrmLite.SqlServer.Core
- ServiceStack.OrmLite.PostgreSQL.Core
- ServiceStack.Core
- ServiceStack.Mvc.Core
- ServiceStack.Server.Core
- ServiceStack.ProtoBuf.Core
- ServiceStack.Wire.Core
- ServiceStack.Aws.Core
- ServiceStack.RabbitMq.Core
- ServiceStack.Stripe.Core
- ServiceStack.Admin.Core
- ServiceStack.Api.Swagger.Core
- ServiceStack.Kestrel
ãŸããã¡ã€ã³ãããžã§ã¯ããšåãã³ãŒãããŒã¹ã§ãããããã€ãã®ç¹ã§è¥å¹²ã®éãããããŸãã ãããããã»ãšãã©ã®ã¿ã¹ã¯ã§ã¯ãæ瀺ãããããã±ãŒãžã¯æå°éã®ã³ã¹ãã§ã³ãŒãã移æ€ããã®ã«ååãªãã®ã«ãªãã§ãããã
çŸåšã®ããã±ãŒãžã®ã³ãŒãã¯ã䞻芳çã«ã¯98ã99ïŒ äžèŽããŠããŸãã .netã³ã¢ã€ã³ãã©ã¹ãã©ã¯ãã£ãµããŒããå¿ èŠãšããå Žæã«ã¯éãããããŸãã å®å šã«æ£ç¢ºã«ããããã«ããããã®ããã±ãŒãžã¯.NET Standart 1.6ãå®å šã«ãµããŒãããŠããŸãã ã€ãŸã å®éããããã¯ãããå®è£ ãããã¹ãŠã®ãã©ãããã©ãŒã ã§äœ¿çšã§ããŸãã 1.6ã¯çŸåšæšæºã®ææ°ããŒãžã§ã³ã§ããããããã¯ãã¹ãŠææ°ã®ãã©ãããã©ãŒã ã§ãã .NET Standard Libraryã®è©³çŽ°ãã芧ãã ããã
çŸåšã®ããŒãžã§ã³ã®æ©èœ
ã³ã³ãã
äœäžçŽãã®éãServiceStackã¯ç¬èªã®DIã³ã³ãããŒFunqã䜿çšããŠããŸããã ASP.NETãã¬ãŒã ã¯ãŒã¯ã¯ä»ã®ãã®ãæäŸããŸããã§ããã ãã¡ãããçŸåšã®Funqãå¥ã®ãæ°ã«å ¥ãã®ã³ã³ãããŒã«çœ®ãæããããšãã§ããŸãããäžè¬ã«ã ååãªçµã¿èŸŒã¿æ©èœããããŸããã
CoreããŒãžã§ã³ã§ã¯ãåŒãç¶ããã«ãã€ã³Funqã䜿çšã§ããŸãããServiceStackã¯ããã.NET Coreã€ã³ãã©ã¹ãã©ã¯ãã£ã®DIã³ã³ãããŒã«åã蟌ã¿ãŸãã å®éã2ã€ã®å Žæããã³ã³ãããæ§æã§ããããã«ãªããŸããã
ã¡ãœããããïŒ
internal class Startup { public void ConfigureServices(IServiceCollection services) { } ... }
ãã©ãããã©ãŒã ã瀺åããããã«ãã¡ãœããããïŒ
internal sealed class ServicesHost : AppHostBase { public override void Configure(Container container) { } ... }
ãã€ãã®ããã«ã ãã ããèæ ®ãã¹ãäž»ãªç¹ã¯ããã®ã¢ãããŒãã§ã¯ããµãŒãã¹ã®ãå¯èŠæ§ãŸãŒã³ãã衚瀺ãããããšã§ãã Startupã¯ã©ã¹ã§å®£èšããããµãŒãã¹ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ãã¹ãŠã®ãã€ã³ãããæå¹ã«ã§ããŸãã ConfigureãªãŒããŒããŒãå ã§èšå®ããããµãŒãã¹ã¯ãServiceStackå ã§ã®ã¿è¡šç€ºãããŸãã .NET Coreã€ã³ãã©ã¹ãã©ã¯ãã£ã«ã¯è¡šç€ºãããŸããã
ãã®ã³ã°
ããã§ããã¹ãŠã®ServiceStackãã®ã³ã°ãæšæºã®.NET Coreãã¬ãŒã«ãããã·ãããŸãã ã€ãŸã ããã§ããµãŒãããŒãã£ã®ã©ã€ãã©ãªã䜿çšããŠSSãã°ãæ¡åŒµããå¿ èŠããªããªããŸããã çµã¿èŸŒã¿ã®LoggerFactoryã®ãã®ã³ã°ãæ¡åŒµããã«ã¯ãããã䜿çšããã ãã§ååã§ã ã
ServiceStack.Authentication
ãªããªã DotNetOpenAuth㯠.NET Coreã«ç§»æ€ãããŠããªãããããã®äŸåé¢ä¿ã«é¢é£ãããã¹ãŠãçŸåšæ©èœããŠããŸããã ç§ã¯ãã®æ©èœã䜿çšããŠããªããããçŸåšã©ã®ããã«ãå£ããããã«ã€ããŠã®è©³çŽ°ã¯ç¥ããŸããã
SOAP
çŸåšã®ããŒãžã§ã³ã§æ¥ç¶ãããŠãããã®ã¯ãã¹ãŠå®å šã«ã¯ãµããŒããããŠããŸããã
ãããããã¡ã€ã©ãŒ
ã¡ã€ã³ãã©ãããã©ãŒã äžã§äŸ¿å©ãªå°ããªããšã¯ãCoreã§ã¯æ©èœããŸããã System.Webãžã®äŸåãå¿ èŠã§ãã
ä»ã®å€æŽããã³ãµããŒããããŠããæ©èœãšãµããŒããããŠããªãæ©èœã«ã€ããŠã¯ã ãã¡ããã芧ãã ãã ã
移æ€ãéå§ããå Žæ
ãããžã§ã¯ããå€é©ããŸã
.NET Coreã«ç§»æ€ããã«ã¯ãäž»ã«2ã€ã®æ¹æ³ããããŸãã
1. project.jsonãã¡ã€ã«ãè¿œå ããŠãçŸåšã®ãã©ã«ããŒããããžã§ã¯ãã«å€æããŸããããã¯ãã»ãšãã©ãã¹ãŠã®* .xprojãã¡ã€ã« ã ã¡ã€ã³é¢æ°ãå«ããã¡ã€ã« ãããã³Starupt.csãã¡ã€ã«ïŒå®éã«ã¯ååã¯äœã§ãããŸããŸããïŒ
2.空ã®ASP.NET Coreã¢ããªãäœæããå€ããããžã§ã¯ããããã¡ã€ã«ãè¿œå ããã ãã§ãã
2çªç®ã®ãªãã·ã§ã³ãããæãŸãã çŸåšã®ãããžã§ã¯ããå€æããã³èª¿æŽããããã®åŽåãå°ãå¿ èŠã§ãã
ãžã®ãªã³ã¯ãè¿œå
æšæºçãªServiceStackããã±ãŒãžãè¿œå ããã ãã§ãäœãçºæããå¿ èŠã¯ãããŸããã
"dependencies": { "Microsoft.AspNetCore.Diagnostics": "1.0.0", "Microsoft.AspNetCore.Server.IISIntegration": "1.0.0", "Microsoft.AspNetCore.Server.Kestrel": "1.0.1", "Microsoft.Extensions.Configuration": "1.0.0", "Microsoft.Extensions.Configuration.FileExtensions": "1.0.0", "Microsoft.Extensions.Configuration.Json": "1.0.0", "Microsoft.Extensions.Configuration.Binder": "1.0.0", "Microsoft.Extensions.Logging.Debug": "1.0.0", "Microsoft.NETCore.App": { "version": "1.0.1", "type": "platform" }, "System.Diagnostics.Tools": "4.0.1", "NLog.Extensions.Logging": "1.0.0-rtm-alpha4", "ServiceStack.Api.Swagger.Core": "1.0.25", "ServiceStack.Client.Core": "1.0.25", "ServiceStack.Common.Core": "1.0.25", "ServiceStack.Core": "1.0.25", "ServiceStack.Interfaces.Core": "1.0.25", "ServiceStack.ProtoBuf.Core": "1.0.25", "ServiceStack.Redis.Core": "1.0.25", "ServiceStack.Text.Core": "1.0.25", "System.Reflection.TypeExtensions": "4.1.0" }
ãšããããNLogãã®ã³ã°ã®æ¡åŒµæ©èœãè¿œå ããŸããã ãããžã§ã¯ãã¯ããã以åã«äœ¿çšããŸããã æ§æã¯nlog.configãã¡ã€ã«ãä»ããŠè¡ãããŸãããããã¯å€ãããŒãžã§ã³ãšå€ãããŸããã
Sturtup.csãå€æŽãã
internal class Startup { private readonly ILoggerFactory _loggerFactory; private readonly ILogger _logger; public Startup(IHostingEnvironment env, ILoggerFactory loggerFactory) { _loggerFactory = loggerFactory; _loggerFactory.AddNLog(); _logger = _loggerFactory.CreateLogger(GetType()); env.ConfigureNLog($"nlog.{env.EnvironmentName}.config"); var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: true, reloadOnChange: true) .AddJsonFile($"appsettings.{env.EnvironmentName}.json", optional: true) .AddEnvironmentVariables(); Configuration = builder.Build(); } public IConfigurationRoot Configuration { get; } public void ConfigureServices(IServiceCollection services) { OrmLiteConfig.DialectProvider = SqlServer2012Dialect.Provider; services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>(); services.AddSingleton(Configuration); services.AddScoped<IDbConnectionFactory>(p => new OrmLiteConnectionFactory(Configuration.GetConnectionString("DefaultConnection"))); services.AddScoped<IRedisClientsManager>(p => new BasicRedisClientManager(Configuration.GetConnectionString("RedisConnectionString"))); services.AddSingleton<ServicesHost>(); } public void Configure(IApplicationBuilder app, IHostingEnvironment env) { _logger.LogInformation(new EventId(1), "Startup started"); var host = (AppHostBase)app.ApplicationServices.GetService(typeof(ServicesHost)); app.UseServiceStack(host); } }
ç§ã¯ãã¹ãŠãã³ã³ããã«ããã¢ãããŒãã䜿çšããŠãããããã¡ã€ã³ã®ServicesHostã¯ã©ã¹ãã³ã³ããã«é 眮ãããŸãã ããã«ãããåŸã®ã³ã³ã¹ãã©ã¯ã¿ãŒã§ãç¬ç«ãã解決ã«é Œãããšãªããå¿ èŠãªäŸåé¢ä¿ãååŸã§ããŸãã
以åã¯ãå€ãã®ãããžã§ã¯ããSystem.Webã¹ããŒã¹ã®ã·ã³ã°ã«ãã³ã䜿çšããŠçŸåšã®Httpã³ã³ããã¹ãã«ã¢ã¯ã»ã¹ããŠããŸããã çŸåšããã®ã¯ã©ã¹ã¯.Net Coreã§ã¯äœ¿çšã§ããŸããã次ã®ãµãŒãã¹ã䜿çšããå¿ èŠããããŸãã
services.TryAddSingleton<IHttpContextAccessor, HttpContextAccessor>();
ããã§ã¯ãå€éšããã®èŠæ±ãããå Žåã«ã®ã¿ã HttpContextAccessor.HttpContextã®å€ãnullãšç°ãªãããšãç¥ãå¿ èŠããããŸãã ãã以å€ã®å Žåãåžžã«nullãå«ãŸããŸã ã
æ§æãã¡ã€ã«ã®æ¥ç¶æ¹æ³ã¯ã appsettingsã ãã§ãªã ã nlogæ§æãªã©ã®ä»ã®è¡ã«ã䜿çšã§ããŸãã
env.ConfigureNLog($"nlog.{env.EnvironmentName}.config");
ã¡ã€ã³ã³ã³ããã§ã¯ããããžã§ã¯ãå ã®ãã¹ãŠã®äŸåé¢ä¿ïŒããŒã¿ã¢ã¯ã»ã¹ã¬ã€ã€ãŒãå€éšãµãŒãã¹ãªã©ïŒãæ§æãããŸãã ServiceStackå ã«ã¯ãSSã®å€éšã®èª°ã䜿çšããªãéåžžã«éãããæ°ã ããæ®ãå¿ èŠããããŸãã
ãµãŒãã¹ãã¹ãã®å€æŽ
ããã¯ãServiceStackç°å¢ãæ§æããããã®äž»èŠãªã³ã³ãããŒã¯ã©ã¹ã§ãããéåžžã¯æ¢ã«å€ããããžã§ã¯ãã«ãããŸãã åãããžã§ã¯ãã§ã¯ç°ãªãæ¹æ³ã§åŒã³åºãããšãã§ããŸãããæ¬è³ªã¯ããã®ã¯ã©ã¹ãAppHostBaseã¯ã©ã¹ããç¶æ¿ãããããšã§ãããããããŒã¿ãã«ãããžã§ã¯ãã®å Žåã§ã¯ãªãå Žåããã®ã¯ã©ã¹ããç¶æ¿ããå¿ èŠããããŸãã
internal sealed class ServicesHost : AppHostBase { private readonly IHttpContextAccessor _accessor; private readonly IAppSettings _settings; private readonly ILogFactory _loggerFactory; private readonly IRedisClientsManager _redisClientsManager; public ServicesHost(IHttpContextAccessor accessor, IAppSettings settings, ILogFactory loggerFactory, IRedisClientsManager redisClientsManager): base(StringsConstants.SERVICES_NAME, typeof(AuthService).GetAssembly()) { _accessor = accessor; _settings = settings; _loggerFactory = loggerFactory; _redisClientsManager = redisClientsManager; } public override void Configure(Container container) { // ConfigurePlugins(); container.RegisterValidators(typeof(RegistrationRequestValidator).GetAssembly()); ConfigureBinders(); // ConfigureGlobalRequestFilters(); // SetConfig(new HostConfig { ApiVersion = StringsConstants.API_VERSION, #if !DEBUG EnableFeatures = Feature.Json | Feature.ProtoBuf | Feature.Html, WriteErrorsToResponse = false, #else EnableFeatures = Feature.Html | Feature.Json | Feature.RequestInfo | Feature.Metadata | Feature.ProtoBuf, WriteErrorsToResponse = true, #endif DebugMode = _settings.Get("DebugMode", false), LogFactory = _loggerFactory, Return204NoContentForEmptyResponse = true, DefaultRedirectPath = "/swagger-ui/", MapExceptionToStatusCode = { {typeof(DomainException), (int) HttpStatusCode.InternalServerError} } }); } ..... }
ç§ã®å Žåãæšæºã®ã¯ãšãªæ€èšŒæ©èœã¯ServiceStackå ã§æ§æãããŠããŸãã ããã«ãã©ãã§ã䜿çšãããŠããŸããã
ãã®ãã¡ã€ã«ã.NET Coreã«ç§»æ€ããè€éãã¯ããããžã§ã¯ãã«ãã£ãŠç°ãªããŸãã æšæºã®SSæ©èœãšã.NET Coreã«æ¢ã«ç§»æ€ãããŠããä»ã®ãµãŒãããŒãã£ããã±ãŒãžã®ã¿ã䜿çšããå Žåããã¡ã€ã«ã®å€æŽã¯æå°éã§æžã¿ãŸãã
System.configuration
ããã¯ãåŸæ¥ã®ASP.NETãã.NET Coreã«ç§»æ€ããéã®æããçããå Žæã®1ã€ã§ãã ServiceAppã¯ã IAppSettingsæœè±¡åã®å®è£ ã§ãå€ãapp / web.configãã¡ã€ã«ã䜿çšããŠäœæ¥ã䜿çšããŸãã 圌ã«appsettings.configãæäœããæ©äŒãäžããã«ã¯ã IAppSettingsã®ããŒãžã§ã³ãå®è£ ããã ãã§ãã ãã®ã¯ã©ã¹ã¯å®éã«ã¯éåžžã«åçŽã§ãServiceStackèªäœã®ã€ã³ãã©ã¹ãã©ã¯ãã£ã®äžéšã䜿çšããŸãã
public class AppSettings : AppSettingsBase { public AppSettings (IConfigurationRoot root, string tier = null) : base(new ConfigurationManagerWrapper(root)) { Tier = tier; } public override string GetString(string name) { return GetNullableString(name); } private class ConfigurationManagerWrapper : ISettings { private readonly IConfigurationRoot _root; private Dictionary<string, string> _appSettings; public ConfigurationManagerWrapper(IConfigurationRoot root) { _root = root; } private Dictionary<string, string> GetAppSettingsMap() { if (_appSettings == null) { var dictionary = new Dictionary<string, string>(); var appSettingsSection = _root.GetSection("appSettings"); if (appSettingsSection != null) { foreach (var child in appSettingsSection.GetChildren()) { dictionary.Add(child.Key, child.Value); } } _appSettings = dictionary; } return _appSettings; } #region Implementation of ISettings public string Get(string key) { string str; if (!GetAppSettingsMap().TryGetValue(key, out str)) return null; return str; } public List<string> GetAllKeys() { return GetAppSettingsMap().Keys.ToList(); } #endregion } }
ã³ã³ããã«äŸåé¢ä¿ãè¿œå ããŠãã ããïŒ
services.AddSingleton<IAppSettings, AppSettings>();
ããã ãã§ã-ããªãã®ãã±ããã«ããappsettings.configãã¡ã€ã«ã®appSettingsã»ã¯ã·ã§ã³ã®èšå®ã
ãããã«
äžèšã§èª¬æããã®ã¯ããã¹ãŠïŒïŒïŒã®å€æŽïŒäžéšã®ã€ã³ã¿ãŒãã§ã€ã¹ã®ååãå€æŽããŠä»ã®ã¯ã©ã¹ã«è»¢éããããšã¯ç°¡åãªããšã§ãïŒãServiceStackã®ãã«ããŒãžã§ã³ã§æžããããããžã§ã¯ãã«è¿œå ããŠãCoreããŒãžã§ã³ã§åäœããããã«ããŸããã
OrmLiteãRedisãTextãClientãããã³ãã®ä»ã®äŸ¿å©ãªããã±ãŒãžã«é¢ãããã¹ãŠã¯ãå€æŽãäžåå¿ èŠãšããŸããã§ããã ãŸããããšãã°ãEFãšåãOrmLiteãéåžžã«æå©ã«åºå¥ããŸãã EFã§èšè¿°ããããããžã§ã¯ããå®å šãª.NETãã.Coreã«ç§»æ€ããã«ã¯ãå€ãã®åŽåãè²»ããå¿ èŠããããŸãã ããã«æäœã¯ãŸã£ããå¿ èŠãããŸãã-ãã¹ãŠãæ©èœããŸãã
å®å šãª.NETã®ãããžã§ã¯ãã§ServiceStackã䜿çšããå Žåã.NET Coreãžã®åãæ¿ãã«ã¯ããªãæéããããå ŽåããããŸãã SSããŒã ã¯ããã¹ãŠãå¯èœãªéãäºææ§ã®ãããã®ã«ããããšããŸããããå®å šã«å¯èœã§ããã ãã¡ãããServiceStackã¯ææã§ãããå人çãªç®çã§ãªãŒãã³ãœãŒã¹ãããžã§ã¯ãã䜿çšããããšãçŠæ¢ãããã®ã¯ãããŸããã
ãããŠãå°ããªã©ã€ãããã¯ã®çµããã«ãéçºäžã®äœ¿çšã«é¢ããå¶éãåé€ããæ¹æ³ïŒæ±ºããŠååã§ã¯ãªãïŒïŒ
1. github.com/ServiceStack/ServiceStack.TextãããŠã³ããŒãããŸã
2. LicenseUtils.csãã¡ã€ã«ã®å¶éãå€æŽããã ããã§ãã¯åŒã³åºããç¡å¹ã«ããŸã
3. Coreãããžã§ã¯ãããŸãšãã
4.ãã¡ã€ã«ãbin \ Release \ netstandart1.3ããïŒ HOMEïŒ \ãNuget \ packages \ ServiceStack.Text.Core \ {ã䜿çšã®ããŒãžã§ã³} \ lib \ netstandart1.3ã«ã³ããŒããŸã
5.å©çïŒ
æ°ããããŒãžã§ã³ã衚瀺ãããå Žåã¯ããã¹ãŠã®æé ãå床å®è¡ããå¿ èŠããããŸãã ãã£ãã·ã¥å šäœãåé€ãããŸã§æããå¿ èŠã¯ãããŸããããèªåã®ãã¢ã»ã³ããªã¯æ¶å»ãããŸããã
PSïŒãããã...ä»ã§ã¯ãã¹ãŠãIISã§ã¯ãªããDockerã³ã³ããã§åäœããŸãã
UPDïŒã³ã¡ã³ãã§ã Scratchã¯å¶éãåé¿ããããã®ãã䟵襲æ§ã®äœããªãã·ã§ã³ãææ¡ããŸããããCoreããŒãžã§ã³ã§ã¯è¥å¹²ç°ãªããŸãïŒ
public static class ServiceStackHelper { static ServiceStackHelper() { var instance = new MyNetStandardPclExport(); PclExport.Instance = instance; NetStandardPclExport.Provider = instance; Licensing.RegisterLicense(string.Empty); } public static void Help() { } private class MyNetStandardPclExport: NetStandardPclExport { public override LicenseKey VerifyLicenseKeyText(string licenseKeyText) { return new LicenseKey { Expiry = DateTime.MaxValue, Hash = string.Empty, Name = "Habr", Ref = "1", Type = LicenseType.Enterprise }; } } }