.NET框架之“小马过河”
.NET框架之“小馬過河”
有許多流行的?.NET框架,大家都覺得挺“重”,認為很麻煩,重量級,不如其它“輕量級”框架,從而不愿意使用。面對形形色色的框架發愁,筆者也曾發愁。但我發現只要敢于嘗試,這些框架都是“紙老虎”。就像“小馬過河”一樣,自己嘗試一下,就會發現“原來河水既不像老牛說的那樣淺,也不像松鼠說的那樣深。”
項目中的代碼,都在?LINQPad6中運行并測試通過,也可以復制到?VisualStudio中執行。
做簡單的?Http服務器很“重”
有些非常簡單的?Http服務器,我看到有些?.NET開發居然也用?Node.js、?Python等語言,一問,他們會回答說“這種簡單的東西,用?.NET,太重了”。殊不知其實用?.NET做起來,也很輕(甚至更輕):
// 代碼不需要引入任何第三方包 var http = new HttpListener(); http.Prefixes.Add("http://localhost:8080/"); http.Start(); while (true) { var ctx = await http.GetContext(); using var writer = new StreamWriter(ctx.Response.OutputStream); writer.Write(DateTime.Now); }運行效果:?
可見,包括空行,僅10行代碼即可完成一個簡單的?HTTP服務器。
使用?EntityFramework很“重”
EntityFramework,簡稱?EF,現在有兩個版本,?EFCore和?EF6,其中?EFCore可以同時運行在?.NETFramework和?.NETCore中,但?EF6只能在?.NETFramework中運行。本文中只測試了?EFCore,但?EF6代碼也一樣簡單。
EntityFramework是?.NET下常用的數據訪問框架,以代碼簡單、功能強大而著名。但不少人卻嗤之以鼻、不以為意。詢問時,回答說?EntityFramework很“重”。
這個“重”字,我理解為它可能占用內存高,或者它可能代碼極其麻煩,配置不方便(像?iBatis/?Hibernate那樣),真的這樣嗎?
如圖,假設我有一個?UserVoiceStatus表:
下面,我們通過?EF將數據取出來:
// 引用NuGet包: // Microsoft.EntityFrameworkCore.SqlServer void Main() { var db = new MyDB(new DbContextOptionsBuilder() .UseSqlServer(Util.GetPassword("ConnectionString")) .Options); db.UserVoiceStatus.Dump(); } public class UserVoiceStatus { public byte Id { get; set; } public string Name { get; set; } } public class MyDB : DbContext { public MyDB(DbContextOptions options): base(options) { } public DbSet<UserVoiceStatus> UserVoiceStatus { get; set; } }執行效果如圖:?
注意,如果使用?LINQPad,事情還能更簡單,只要一行代碼即可,效果完全一樣:?UserVoiceStatuses
使用?ASP.NET MVC很“重”
上文說到了如何做一個簡單的?Http服務器,如果想復雜一點,初始化?ASP.NET MVC也很簡單,甚至只需要一個文件即可完成:
void Main() { WebHost .CreateDefaultBuilder() .UseStartup<UserQuery>() .UseUrls("https://localhost:55555") .Build() .Run(); } public void ConfigureServices(IServiceCollection services) { services.AddControllers(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapControllerRoute( name: "default", pattern: "{controller}/{action}/{id?}", defaults: new { controller = "Home", action = "Index" }); }); } namespace Controllers { public class HomeController : Controller { public DateTime Index() { return DateTime.Now; } } }麻雀雖小,五臟俱全,這么簡短的幾千代碼中,可以使用?Https、包含了依賴注入,還能完整的路由功能,就構成了?ASP.NET MVC的基本代碼。運行效果如圖:?
使用?WebSockets很“重”
WebSockets是個流行的?Http雙向通信技術,以前在?Node.js中很流行(用?socket.io)。代碼如下:
async Task Main() { await WebHost .CreateDefaultBuilder() .UseStartup<UserQuery>() .UseUrls("https://*:55555") .Build() .RunAsync(); } async Task Echo(HttpContext ctx, WebSocket webSocket, CancellationToken cancellationToken) { var buffer = new byte[4096]; ValueWebSocketReceiveResult result = await webSocket.ReceiveAsync(buffer.AsMemory(), cancellationToken); while (!result.EndOfMessage) { await webSocket.SendAsync(buffer.AsMemory(..result.Count), result.MessageType, result.EndOfMessage, cancellationToken); result = await webSocket.ReceiveAsync(buffer.AsMemory(), cancellationToken); } await webSocket.CloseAsync(WebSocketCloseStatus.NormalClosure, "NA", cancellationToken); } public void ConfigureServices(IServiceCollection services) { } public void Configure(IApplicationBuilder app) { app.UseWebSockets(); app.Use(async (ctx, next) => { if (ctx.Request.Path == "/ws") { if (ctx.WebSockets.IsWebSocketRequest) { WebSocket webSocket = await ctx.WebSockets.AcceptWebSocketAsync(); await Echo(ctx, webSocket, CancellationToken.None); return; } } await next(); }); app.Run(x => x.Response.WriteAsync("Please call /ws using WebSockets.")); }該代碼是個?Echo服務器,它會將客戶端發過來和內容,按原因返回給客戶端。然后,?.NET也內置了?WebSockets的客戶端:可以高效地訪問剛剛創建并運行的?WebSockets服務器。
using (var ws = new ClientWebSocket()) { await ws.ConnectAsync(new Uri("wss://localhost:55555/ws"), CancellationToken.None); var completeEvent = new ManualResetEventSlim(); var cts = new CancellationTokenSource(); new Task(() => SendMessage(ws, cts)).Start(); var buffer = new byte[4096]; do { var r = await ws.ReceiveAsync(buffer, cts.Token); $"[{Util.ElapsedTime}] Received {Encoding.UTF8.GetString(buffer, 0, r.Count)}".Dump(); } while (ws.State != WebSocketState.Closed); } $"[{Util.ElapsedTime}] Closed.".Dump(); async void SendMessage(WebSocket ws, CancellationTokenSource cts) { for (var i = 0; i < 3; ++i) { await ws.SendAsync( Encoding.UTF8.GetBytes($"[{Util.ElapsedTime}] Send {DateTime.Now.ToString()}".Dump()), WebSocketMessageType.Text, endOfMessage: false, default); await Task.Delay(1000); } await ws.CloseAsync(WebSocketCloseStatus.Empty, null, default); cts.Cancel(); }最后,客戶端與服務器雙向通信效果如下:?
使用?SignalR很“重”
SignalR是?ASP.NET推出的抽象式的?Http協議雙向通信框架。?SignalR可以用相同的?API,支持像長輪詢、?ServerSentEvents和?WebSocket的技術。?SignalR默認優先選擇使用?WebSocket以達到最高性能,如果客戶端或服務器不支持,則會回退至其它稍慢的技術。
SignalR客戶端還支持幾乎所有語言、所有平臺。它是如此好用,幾乎可以取代傳統的請求/響應,成為新的?Http開發模型。(事實上?Blazor正在嘗試這樣做)
但?SignalR最為令人震撼的,還是它非常簡單的使用方式,而恰恰是這一點給人誤會最深。它的服務端?API,甚至比?WebSocket還要簡單清晰簡單:
async Task Main() { await WebHost .CreateDefaultBuilder() .UseStartup<UserQuery>() .UseUrls("https://localhost:55555") .Build() .RunAsync(); } public void ConfigureServices(IServiceCollection services) { services.AddSignalR(); } public void Configure(IApplicationBuilder app) { app.UseRouting(); app.UseEndpoints(endpoints => { endpoints.MapHub<Hubs.ChatHub>("/chat"); }); } namespace Hubs { public class ChatHub : Hub { public async Task Broadcast(string id, string text) { await Clients.All.SendAsync("Broadcast", id, text); } } }前文提到,?SignalR提供了所有平臺的?SignalR客戶端,如?js、?Android等,其中當然(顯然)也包括?.NET的。?SignalR的?.NET客戶端使用起來也非常簡單:
// 引入NuGet包:Microsoft.AspNetCore.SignalR.Client // 代碼在LINQPad中運行 var hub = new HubConnectionBuilder() .WithUrl("https://localhost:55555/chat") .Build(); hub.On("Broadcast", (string id, string msg) => { Console.WriteLine($"{id}: {msg}"); }); new Label("姓名: ").Dump(); var idBox = new TextBox(Guid.NewGuid().ToString()).Dump(); await hub.StartAsync(); while (true) { var text = Console.ReadLine(); if (text == "Q") break; await hub.SendAsync("Broadcast", idBox.Text, text); }這是一個非常簡單的多人聊天室,運行效果如下:?
總結
面對形形色色的框架發愁,筆者也曾發愁。但現在不了,什么框架拿過來,馬上試試,也就幾十秒鐘的事。好用不好用,用用便知。
那么讀者,你的“小馬過河”的故事是怎樣的呢?
總結
以上是生活随笔為你收集整理的.NET框架之“小马过河”的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: asp.net core 使用 sign
- 下一篇: ML.NET 示例:搜索引擎结果排名