.NET Core 1.0 初探:跨平台的新时代
2016.09.14
C#
3 min
1.2k 字
// 目录 · contents
2016 年 6 月,微软正式发布了 .NET Core 1.0,这是 .NET
平台历史上最大的一次架构重构。作为一个长期在 Windows 上写 C#
的开发者,第一次在 macOS 上 dotnet run
成功时确实有点难以置信。这篇文章记录我的上手体验和核心认知。
1. .NET Core 是什么
.NET Core 不是 .NET Framework
的升级版,而是从零重写的跨平台运行时:
| 平台 |
Windows only |
Windows / Linux / macOS |
| 部署方式 |
全局安装 |
可随应用自包含 |
| 包管理 |
GAC + NuGet |
纯 NuGet |
| Web 框架 |
ASP.NET (System.Web) |
ASP.NET Core(完全重写) |
| 体积 |
大(几百MB运行时) |
轻量(可裁剪) |
| 开源 |
否 |
是(MIT) |
最大的变化是 System.Web 消失了。ASP.NET
Core 不再依赖 IIS 的 HttpModule/HttpHandler
架构,而是从零构建了一套全新的请求管道。这意味着大量 ASP.NET MVC 4/5
的代码不能直接迁移,需要重写。
2. 第一个 ASP.NET Core 1.0
应用
项目结构相比 MVC 5 简化了很多:
1 2 3 4 5 6 7 8 9
| MyApp/ ├── Controllers/ │ └── HomeController.cs ├── Views/ │ └── Home/Index.cshtml ├── wwwroot/ # 静态文件根目录(新增) ├── appsettings.json # 配置文件(替代 web.config) ├── Program.cs # 应用入口 └── Startup.cs # 应用配置(新)
|
Program.cs(应用入口,类似控制台程序):
1 2 3 4 5 6 7 8 9 10 11 12 13 14
| public class Program { public static void Main(string[] args) { var host = new WebHostBuilder() .UseKestrel() .UseContentRoot(Directory.GetCurrentDirectory()) .UseIISIntegration() .UseStartup<Startup>() .Build();
host.Run(); } }
|
Startup.cs(服务注册 + 中间件配置):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45
| public class Startup { public IConfigurationRoot Configuration { get; }
public Startup(IHostingEnvironment env) { var builder = new ConfigurationBuilder() .SetBasePath(env.ContentRootPath) .AddJsonFile("appsettings.json", optional: false, reloadOnChange: true) .AddEnvironmentVariables();
Configuration = builder.Build(); }
public void ConfigureServices(IServiceCollection services) { services.AddMvc(); services.AddDbContext<AppDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("Default"))); services.AddScoped<IUserService, UserService>(); }
public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory) { if (env.IsDevelopment()) { app.UseDeveloperExceptionPage(); } else { app.UseExceptionHandler("/Home/Error"); }
app.UseStaticFiles(); app.UseMvc(routes => { routes.MapRoute( name: "default", template: "{controller=Home}/{action=Index}/{id?}"); }); } }
|
3. 内置依赖注入
这是 ASP.NET Core 最重要的改变之一:DI
是框架的一等公民,无需引入第三方容器。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
| services.AddTransient<IEmailService, SmtpEmailService>(); services.AddScoped<IOrderService, OrderService>(); services.AddSingleton<ICacheService, RedisCacheService>();
public class OrdersController : Controller { private readonly IOrderService _orderService; private readonly ILogger<OrdersController> _logger;
public OrdersController(IOrderService orderService, ILogger<OrdersController> logger) { _orderService = orderService; _logger = logger; } }
|
与 MVC 5 需要手动集成 Autofac 相比,内置 DI
大大降低了项目的启动成本。
4. 配置系统
web.config 退场,新的配置系统支持多源合并:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| { "ConnectionStrings": { "Default": "Server=localhost;Database=myapp;..." }, "App": { "MaxRetries": 3, "Timeout": 30 } }
string connStr = Configuration.GetConnectionString("Default"); int maxRetries = Configuration.GetValue<int>("App:MaxRetries");
services.Configure<AppSettings>(Configuration.GetSection("App"));
public class MyService { private readonly AppSettings _settings; public MyService(IOptions<AppSettings> options) { _settings = options.Value; } }
|
5. 在 Linux 上运行
1 2 3 4 5 6 7 8 9 10 11
| curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg sudo apt-get install dotnet-dev-1.0.4
dotnet new mvc -o MyApp cd MyApp dotnet restore dotnet run
|
第一次在 Linux 上跑起来 C# Web 应用,感觉还是挺震撼的。
个人感受
.NET Core 1.0 还很早期,有一些明显的不足:API 覆盖率不完整(很多 .NET
Framework 的类库还没移植),工具链也不够成熟,项目格式是
project.json 而不是
.csproj(这个在后来的版本改回来了)。
但方向是对的。内置 DI、中间件管道、可自托管的
Kestrel——这套架构比老的 ASP.NET
干净多了。我当时的判断是:如果是全新项目,值得考虑
Core;老项目迁移代价太大,先观望。
现在回头看,这个判断基本正确:.NET Core 2.0
之后才真正成熟,那时候迁移才比较顺畅。