.NET框架之“小马过河”

有许多流行的.NET框架,大家都觉得挺“重”,认为很麻烦,重量级,不如其它“轻量级”框架,从而不愿意使用。面对形形色色的框架发愁,笔者也曾发愁。但我发现只要敢于尝试,这些框架都是“纸老虎”。就像“小马过河”一样,自己尝试一下,就会发现“原来河水既不像老牛说的那样浅,也不像松鼠说的那样深。”

项目中的代码,都在LINQPad 6中运行并测试通过,也可以复制到Visual Studio中执行。

做简单的Http服务器很“重”

有些非常简单的Http服务器,我看到有些.NET开发居然也用Node.jsPython等语言,一问,他们会回答说“这种简单的东西,用.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服务器。

使用Entity Framework很“重”

Entity Framework,简称EF,现在有两个版本,EF CoreEF 6,其中EF Core可以同时运行在.NET Framework.NET Core中,但EF 6只能在.NET Framework中运行。本文中只测试了EF CoreEF 6代码也一样简单

Entity Framework.NET下常用的数据访问框架,以代码简单、功能强大而著名。但不少人却嗤之以鼻、不以为意。询问时,回答说Entity Framework很“重”。

这个“重”字,我理解为它可能占用内存高,或者它可能代码极其麻烦,配置不方便(像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很“重”

SignalRASP.NET推出的抽象式的Http协议双向通信框架。SignalR可以用相同的API,支持像长轮询、Server Sent EventsWebSocket的技术。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客户端,如jsAndroid等,其中当然(显然)也包括.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);
}

这是一个非常简单的多人聊天室,运行效果如下:

总结

面对形形色色的框架发愁,笔者也曾发愁。但现在不了,什么框架拿过来,马上试试,也就十几秒钟的事。好用不好用,用用便知。

那么读者,你的“小马过河”的故事是怎样的呢?

请关注我的微信公众号:【DotNet骚操作】,

.NET框架之“小马过河”的更多相关文章

  1. Xamarin Forms:小马过河,王者归来

    因为我媳妇的原因,去年下半年从零开始学习Android原生开发,做了一个答题库app.整体给我的感觉是入门难度不大,前期折腾一番,大部分时间都是花在开发上面,其实任何一门语言都是如此. 今年我又有另一 ...

  2. 牛客网 牛客小白月赛2 B.小马过河-简单的计算几何

    B.小马过河 链接:https://www.nowcoder.com/acm/contest/86/B 这个题是一个简单的几何题???套个板子就过了,就是直线上两点确定的这条直线和直线外一点的垂足的坐 ...

  3. Win7激活工具|OEM小马激活

    OEM小马激活,Win7激活. 免费下载:http://yunpan.cn/cmZ5DyDvXG2In  访问密码 7fcf

  4. EF框架搭建小总结--CodeFirst模型优先

    前言:之前在下总结编写了一篇 EF框架搭建小总结--ModelFirst模型优先 博文,看到一段时间内该博文的访问量蹭.蹭蹭.蹭蹭蹭...往上涨(实际也不是很多,嘿嘿),但是还是按捺不住内心的喜悦(蛮 ...

  5. Django中的ORM框架使用小技巧

      Django中的ORM框架使用小技巧 作者:尹正杰  版权声明:原创作品,谢绝转载!否则将追究法律责任. Django对各个数据提供了很好的支持,包括PostgreSQL,MySQL,SQLite ...

  6. EF框架搭建小总结--CodeFirst代码优先

    前言:之前在下总结编写了一篇 EF框架搭建小总结--ModelFirst模型优先 博文,看到一段时间内该博文的访问量蹭.蹭蹭.蹭蹭蹭...往上涨(实际也不是很多,嘿嘿),但是还是按捺不住内心的喜悦(蛮 ...

  7. 一个用户管理的ci框架的小demo--转载

    一个ci框架的小demo 最近在学习ci框架,作为一个初学者,在啃完一遍官方文档并也跟着官方文档的例程(新闻发布系统)做了一遍,决定在将之前练习PHP与MySQL数据库的用户管理系统再用ci框架实现一 ...

  8. wepy框架构建小程序(1)

    wepy框架构建小程序(1) 基本操作: # 安装脚手架工具 npm install wepy-cli -g # 创建一个新的项目 npm init standard myproject # 进入新项 ...

  9. Scratch编程:快乐的小马(三)

    “ 上节课的内容全部掌握了吗?反复练习了没有,编程最好的学习方法就是练习.练习.再练习.一定要记得多动手.多动脑筋哦~~” 01 — 游戏介绍 这是一款简单的小游戏,实现了一匹小马跑来跑去(小马有跑动 ...

随机推荐

  1. MQ服务器端和客户端通信浅谈

    MQ服务器端和客户端通信浅谈 1. WebSphere MQ的服务端的安装和配置 (1)创建名为venus.queue.manager的默认队列管理器. 在DOS窗口命令提示符下,输入以下命令: cr ...

  2. Java虚拟机(二)-对象创建

    这一篇大致说明一下,对象在Java堆中对象分配.内存布局以及访问定位 1.对象的创建 虚拟机在遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引 ...

  3. HlpViewer.exe 单独打开

    1.在桌面新建一个快捷键 2.添加HlpViewer.exe 的本地地址 3.在添加的地址后面添加 /catalogName VisualStudio12 4.保存快捷键即可 列: 桌面右键-> ...

  4. ASP.NET CORE 2.* 利用集成测试框架覆盖HttpClient相关代码

    ASP.NET CORE 集成测试官方介绍 我的asp.net core 项目里面大部分功能都是去调用别人的API ,大量使用HttpClient,公司单元测试覆盖率要求95%以上,很难做到不mock ...

  5. Kubernetes-保障集群内节点和网络安全

    13.1.在pod中使用宿主节点的Linux命名空间 13.1.1.在pod中使用宿主节点的网络命名空间 在pod的yaml文件中就设置spec.hostNetwork: true 这个时候pod使用 ...

  6. Git 实用技巧:git stash

    我们经常会遇到这样的情况: 正在dev分支开发新功能,做到一半时有人过来反馈一个bug,让马上解决,但是新功能做到了一半你又不想提交,这时就可以使用git stash命令先把当前进度保存起来.然后切换 ...

  7. 如何添加JWT生成的token在请求头中

    前言 在我们使用JWT来做用户的验证时,我们登陆生成对应的token,并加入到请求的参数中发送到后台提供相关的权限校验.这个时候我们需要使用到传递请求头参数传递的问题,下面是两种方式. 1.ajax提 ...

  8. 运行所选代码生成器时出错:“值-1超出了可接受的[0,2147483647]范围。参数名称:value”

    在使用vs2019添加mvc控制器的时候 这已经是第二次遇到这个问题了.常言道,多喝热水,重启试试.有时候当应用工作不正常,重启也许能解决问题.但是程序员通常接触不到服务器系统权限.而运维人员和公司流 ...

  9. Guava 常用工具类

    引入guava包: <dependency> <groupId>com.google.guava</groupId> <artifactId>guava ...

  10. PIXIJS的一些使用

    我发现pixijs在国内简直就是一片静土啊,只有那么一点点的微弱的不能再微弱的声音. 我在这里整理了下我使用过程中解决和可能理解的一些问题吧,都是一个个点,而不是完整的示例. 先放官网示例: http ...