1. 程式人生 > >.NET框架之“小馬過河”

.NET框架之“小馬過河”

.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框架

.NET框架之“小馬過河” 有許多流行的.NET框架,大家都覺得挺“重”,認為很麻煩,重量級,不如其它“輕量級”框架,從而不願意使用。面對形形色色的框架發愁,筆者也曾發愁。但我發現只要敢於嘗試,這些框架都是“紙老虎”。就像“小馬過河”一樣,自己嘗試一下,就會發現“原來河水既不像老牛說的那樣淺,也不像松鼠說的那

的故事要銘記

參考地址:http://blog.sina.com.cn/s/blog_14ac05d9c0102wujf.html 解決方案一:<br> $indexModel = D('Index'); <wbr> 實測可行<br> 解決方案一:&l

們的 小馬 身邊 自己 如果 就是 一個 就會 請您 馬棚裏住著一匹老馬和一匹小馬。  有一天,老馬對小馬說:“你已經長大了,能幫媽媽做點事嗎?”小馬連蹦帶跳地說:“怎麽不能?我很願意幫您做事。”老馬高興地說:“那好哇,你把這半口袋麥子馱到磨坊去吧。”  小馬馱起麥子,飛快

RDIFramework.NET 框架組織機構許可權設定

RDIFramework.NET 框架之組織機構許可權設定   對於某些大型的企業、資訊系統,涉及的組織機構較多,模組多、操作許可權也多,對使用者或角色一一設定模組、操作許可權等比較繁瑣。我們可以直接對某一組織機構進行許可權的設定,這樣設定後,同一組織機構的使用者就可以擁有相應的模組訪問許可權,操作許可權了

.NET框架---MEF託管可擴充套件框架

MEF簡介: 今天學習了下MEF框架,MEF,全稱Managed Extensibility Framework(託管可擴充套件框架)。MEF是專門致力於解決擴充套件性問題的框架,MSDN中對MEF有這樣一段說明:   Managed Extensibility Frame

遞推問題卒問題

-a 固定 能夠 沒有 就是 數據 nbsp size turn problem 棋盤上A點有一個過河卒,需要走到目標B點。卒行走的規則:可以向下、或者向右。同時在棋盤上C點有一個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因此稱之為“馬攔

ORM框架------Dapper,Net下無敵的ORM

官網 結果集 vid 方便 喜歡 完全 字符 sqlite數據庫 工作 一,介紹:Dapper是一款輕量級ORM工具。如果你在小的項目中,使用Entity Framework、NHibernate 來處理大數據訪問及關系映射,未免有點殺雞用牛刀。你又覺得ORM省時省力,

NET Core應用框架BitAdminCore框架應用篇系列

net EDA clas IE span targe slist target nco BitAdminCore是基於NET Core2.0的後端快速開發框架,本篇主要目標是介紹如何使用框架開發應用。框架的一些特性等。 系列鏈接 BitAdminCore框架應用

科普!嘟嘟屬於幾線品牌 和其他童裝的不同

盡心 通過 顏色 出現 體重 小馬 截取 產品研發 負責人 家長都希望自己的孩子在各個方面都能夠出彩,於是給予自己的 孩子更好的東西,在童裝方面更能引起消費共鳴。因而一些品牌紛紛抓住家長們這一心理,任意提高其產品的價格,而家長們也無力改變。那麽,童裝市場上是否還有好的

經典動態規劃卒【洛谷 P1002】

傳送門 因為小兵只能往右走和往下走 所以動態轉移方程為map[i][j]=map[i-1][j]+map[i][j-1] 感覺上。。是很經典的。 題目描述 棋盤上AAA點有一個過河卒,需要走到目標BBB點。卒行走的規則:可以向下、或者向右。同時在棋盤上CCC點有一個對方的馬,該馬所在

2018最新全WAF/CDN/D盾/安全狗Or大馬

2018最新過全WAF/CDN/D盾/安全狗小馬Or大馬 首先感謝土司大佬:Math_random 上程式碼—注意菜刀連結密碼為:ximcx <?php $x="BaSe64"; $b="_deCOde"; $c=$x.$b; eval($cc = $c('JGhh

Asp.net 面向介面可擴充套件框架業務規則引擎擴充套件元件

原文: Asp.net 面向介面可擴充套件框架之業務規則引擎擴充套件元件 隨著面向介面可擴充套件框架的繼續開發,有些功能開發出現了"瓶頸",有太多的東西要寫死才好做。但寫死的程式碼擴充套件性是非常的不好,迷茫中尋找出入... 進而想到我以前開發的好幾個專案,都已有一定的可配置能力,想想怎麼把這些地方的程式

Asp.net 面向介面可擴充套件框架資料處理模組及EntityFramework擴充套件和Dapper擴充套件(含乾貨)

原文: Asp.net 面向介面可擴充套件框架之資料處理模組及EntityFramework擴充套件和Dapper擴充套件(含乾貨) 介面資料處理模組是什麼意思呢?實際上很簡單,就是使用面向介面的思想和方式來做資料處理。 還提到EntityFramework和Dapper,EntityFramework和

GO語言Beego框架WEB安全系統(5)跨目錄上傳檔案漏洞

跨目錄上傳檔案漏洞 攻擊原理 絕對路徑名或者相對路徑名中可能會包含檔案連結(例如:軟連結、硬連結、快捷方式、影子檔案、別名等),或者包含特殊字元(例如:.與..),這使得驗證檔案路徑變得困難;同時還有很多作業系統和檔案系統相關的命名約定,也增加了驗證檔案路

p1293

題目 描述 Description   棋盤上A點有一個過河卒,需要走到目標B點。卒行走的規則:可以向下、或者向右。同時在棋盤上C點有一個對方的馬,該馬所在的點和所有跳躍一步可達的點稱為對方馬的控制點。因此稱之為“馬攔過河卒”。   棋盤用座標表示,A點(0, 0)、B點(n, m

從壹開始前後端分離【 .NET Core2.0 +Vue2.0 】框架十二 || 三種跨域方式比較,DTOs(資料傳輸物件)初探

更新反饋 1、博友@童鞋說到了,Nginx反向代理實現跨域,因為我目前還沒有使用到,給忽略了,這次記錄下,為下次補充。 程式碼已上傳Github+Gitee,文末有地址   今天忙著給小夥伴們提出的問題解答,時間上沒把握好,都快下班了,趕緊釋出:書說上文《從壹開始前

unittest單元測試框架測試用例的跳(skip) (六)

1.跳過測試用例的方法 @unittest.skip("don't run this case!"): @unittest.skipIf(3<2,"don't run this case!"): @unittest.skipUnless(3>2,"don't run this ca

B/S開發框架Web安全問題及防範規範和WebShell

信息 處理程序 自動運行 code 被攻擊 保存 完全 進程模型 catch Web站點為什麽會遭受攻擊?是為了惡作劇?損害企業名譽?免費瀏覽收費內容?盜竊用戶隱私信息?獲取用戶賬號謀取私利?總之攻擊方式層出不窮,作為B/S開發框架來說,幫助開發者做好解決安

分享哥Spring Boot 2.0深度實踐核心技術篇

第1章 系列總覽 總覽 Spring Boot 2.0 深度實踐系列課程的整體議程,包括 Spring Boot 三大核心特性(元件自動裝配、嵌入式Web容&#64056;、生產準備特性)、Web 應用(傳統 Servlet、Spring Web MVC、Spri

The Little Book of Semaphores 訊號量書 第五章 稍欠經典的同步問題 5.7 問題

第五章 稍欠經典的同步問題 5.7 過河問題 這個問題來自於加州大學伯克利分校的安東尼·約瑟夫寫的問題集,但我不知道他是不是原作者。 它類似於H2O問題,因為它是一種特殊的屏障,只允許執行緒以某種組合通過。  在華盛頓州雷德蒙德附近,有一艘划艇,Linux黑客和微軟