.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, , 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);
}
这是一个非常简单的多人聊天室,运行效果如下:
总结
面对形形色色的框架发愁,笔者也曾发愁。但现在不了,什么框架拿过来,马上试试,也就几十秒钟的事。好用不好用,用用便知。
那么读者,你的“小马过河”的故事是怎样的呢?
推荐阅读:苹果x和xr
-
凯特王妃穿三万礼服裙,与威廉王子同坐“三蹦子
近日,威廉王子携凯特王妃现身巴基斯坦伊斯兰堡,参加英国高级专员托马斯·德鲁为他们举办的招待会,这次王室夫妇都选择了一身墨绿色的晚礼服,其中凯特王妃的墨绿色亮片礼...
2019-10-17 -
《竹马钢琴师》今日开播 文苡帆暖心演绎钢琴王
Yes娱乐10月17日综合报导今日,由方逸伦、文苡帆、金雯昕等主演的青春校园励志剧《竹马钢琴师》将于中午十二点在优酷视频和芒果TV全网首播。该剧讲述了相识于少年...
2019-10-17 -
毛晓彤遭泰国男星Mike追求,虽有好感却不敢
说到毛晓彤,大概大家想到的都是她之前和陈翔分手的事情,还有被自己的亲生父亲追债的事情,其实关于这两件备受争议的事情,毛晓彤的处理一向都是非常低调的,她并没有公开...
2019-10-17 -
爱奇艺今年Q4以及明年备播大剧,好剧接连不断
日前,爱奇艺举行电视剧招商,公布了爱奇艺备播片单,多部国产热剧一网打尽!提前了解一下(79部,其中独播11部):必买大剧系列1.娄艺潇、李佳航、孙艺洲《爱情公寓...
2019-10-17 -
杜飞颜值衣品均甩何书桓几条街!是如萍瞎了还是
《情深深雨濛濛》真是一部神剧啊!算起来琼瑶阿姨的剧都称得上是神剧,神在三观:)无论是《还珠格格》中五阿哥和知画生孩子,还是《新月格格》中养女和养父在一起,还获得...
2019-10-17 -
《初恋那件小事》终于官宣,谁注意赵今麦造型?
相信对于甜宠剧,大家都是十分喜欢的。而近来也出现过不少新的甜宠剧,就像是《不负时光》《世界欠我一个初恋》等,都得到了大家的一致好评。不过,近来大家倒是对另外一部...
2019-10-17 -
今日爆料:热巴恋爱了?杨幂造型翻车?
1迪丽热巴恋爱了?今日,迪丽热巴的某综艺短片下篇上线,她在节目中穿上了婚纱,拍了一个人的婚纱照,并表示希望遇见爱情。对此,不少瓜众都质疑她是不是已经谈恋爱了,在...
2019-10-17 -
2019热剧播放量排行榜TOP 10!第一名
2019暑期黄金档最火的当然就是李现和杨紫《亲爱的,热爱的》,还有肖战和王一博《陈情令》、张震和倪妮《宸汐缘》。日前大陆一份最新数据整理出暑期上文件的电视剧的累...
2019-10-17