優雅的在WinForm/WPF/控制台 中使用特性封裝WebApi

来源:https://www.cnblogs.com/Yann123/archive/2019/08/16/11365669.html
-Advertisement-
Play Games

優雅的在WinForm/WPF/控制台 中使用特性封裝WebApi 說明 ` 在C/S端作為Server,建立HTTP請求,方便快捷。 ` 1.使用到的類庫 ` Newtonsoft.dll ` 2.封裝 HttpListener HttpApi類 特性類 ActionName 特性類 HttpMe ...


優雅的在WinForm/WPF/控制台 中使用特性封裝WebApi

說明

在C/S端作為Server,建立HTTP請求,方便快捷。

1.使用到的類庫

Newtonsoft.dll

2.封裝 HttpListener

HttpApi類
    public class HttpApi
    {

        private static List<HttpListener> HttpListenerList = new List<HttpListener>();

        /// <summary>
        /// 初始化服務
        /// </summary>
        public static void InitService()
        {

            //獲取程式集下麵的所有的類
            Type[] types = System.Reflection.Assembly.GetExecutingAssembly().GetTypes();
            foreach (Type item_type in types)
            {
                //定義是否有類的特性標識
                bool IsHasFormApi = false;
                //取類上的自定義特性
                object[] objs = item_type.GetCustomAttributes(typeof(FromApi), true);
                foreach (object obj in objs)
                {
                    FromApi fromApi = obj as FromApi;
                    if (fromApi != null)
                    {
                        IsHasFormApi = true;
                        break;
                    }
                }
                if (IsHasFormApi)
                {
                    // 獲取完全名稱
                    String className = item_type.FullName;

                    // 根據命名空間反射類的Type
                    Type type = Type.GetType(className);
                    object objInstance = type.Assembly.CreateInstance(className);

                    // 獲取所有的方法
                    MethodInfo[] info = type.GetMethods();

                    // 遍歷所有的方法
                    foreach (MethodInfo item in info)
                    {

                        // 獲取Http請求方法
                        HttpMethod httpMethod = item.GetCustomAttribute<HttpMethod>();
                        // 獲取Action
                        ActionName actionName = item.GetCustomAttribute<ActionName>();

                        // 判斷有沒有特性
                        if (httpMethod != null || actionName != null)
                        {
                            HttpListener listerner = new HttpListener();
                            listerner.AuthenticationSchemes = AuthenticationSchemes.Anonymous;//指定身份驗證 Anonymous匿名訪問
                            string url = "http://127.0.0.1:8011";
                            if (!string.IsNullOrEmpty(ConfigurationManager.AppSettings["httpserver"]))
                            {
                                url = "http://" + ConfigurationManager.AppSettings["httpserver"];
                            }
                            listerner.Prefixes.Add(url + actionName.URL + "/");

                            //開啟服務
                            if (!listerner.IsListening)
                            {
                                listerner.Start();
                                AsyncCallback ac = new AsyncCallback(GetContextAsyncCallback);
                                CallbackObject callback = new CallbackObject() { Listerner = listerner, MethodItem = item, ClassInstance = objInstance, HttpMethod = httpMethod.method };
                                listerner.BeginGetContext(ac, callback);
                                HttpListenerList.Add(listerner);
                            }
                        }

                    }
                }
            }


        }

        /// <summary>
        /// 收到監聽請求回調
        /// </summary>
        /// <param name="ia"></param>
        private static void GetContextAsyncCallback(IAsyncResult ia)
        {
            CallbackObject state = ia.AsyncState as CallbackObject;
            if (ia.IsCompleted)
            {
                HttpListenerContext ctx = state.Listerner.EndGetContext(ia);

                var request = ctx.Request;

                HttpListenerResponse response = ctx.Response;


                try
                {

                    //判斷 請求 方式
                    if (request.HttpMethod.ToUpper() == state.HttpMethod.ToString().ToUpper() || Method.All.ToString().ToUpper() == state.HttpMethod.ToString().ToUpper())
                    {
                        string rawData;

                        using (var reader = new StreamReader(request.InputStream, request.ContentEncoding))
                        {
                            rawData = reader.ReadToEnd();
                        }


                        //獲取方法參數列表

                        ParameterInfo[] parameterInfos = state.MethodItem.GetParameters();

                        //參數
                        // List<object> paramters = new List<object>();
                        object[] paramters = new object[parameterInfos.Length];

                        for (int i = 0; i < parameterInfos.Length; i++)
                        {
                            ParameterInfo item = parameterInfos[i];
                            if (item.ParameterType == typeof(string) || item.ParameterType == typeof(int) || item.ParameterType == typeof(bool))
                            {
                                paramters[i] = JsonHelper.GetJsonValue(rawData, item.Name);
                            }
                            else
                            {
                                Type t = item.ParameterType;
                                paramters[i] = JsonConvert.DeserializeObject(rawData, t);
                            }
                        }


                        object resobj = state.MethodItem.Invoke(state.ClassInstance, paramters);
                        if (typeof(string) == resobj.GetType())
                        {
                            ResponseWrite(response, resobj.ToString());
                        }
                        else
                        {
                            ResponseWrite(response, JsonConvert.SerializeObject(resobj));
                        }
                    }
                    else
                    {
                        ResponseWrite(response, $"不支持{request.HttpMethod.ToUpper()}方法請求!");
                    }
                }
                catch (Exception ex)
                {
                    ResponseWrite(response, $"服務出現異常,異常信息:{ex.Message}");
                }
            }

            //重新監聽  不寫的話只能調用一次 
            AsyncCallback ac = new AsyncCallback(GetContextAsyncCallback);
            state.Listerner.BeginGetContext(ac, state);
        }

        /// <summary>
        /// 回寫響應
        /// </summary>
        /// <param name="response"></param>
        /// <param name="Content"></param>
        private static void ResponseWrite(HttpListenerResponse response, string Content)
        {
            //使用Writer輸出http響應代碼
            using (System.IO.StreamWriter writer = new System.IO.StreamWriter(response.OutputStream, new UTF8Encoding()))
            {
                response.ContentType = "application/json; charset=utf-8";
                writer.WriteLine(Content);
                writer.Close();
                response.Close();
            }
        }
    }



    public enum Method
    {
        All, Post, Get
    }

    public class CallbackObject
    {
        /// <summary>
        /// 監聽
        /// </summary>
        public HttpListener Listerner { get; set; }

        /// <summary>
        /// 方法
        /// </summary>
        public MethodInfo MethodItem { get; set; }

        /// <summary>
        /// 調用者 對象
        /// </summary>
        public object ClassInstance { get; set; }

        /// <summary>
        /// 調用方式 Get Post
        /// </summary>
        public Method HttpMethod { get; set; }
    }
特性類 ActionName
    [AttributeUsage(AttributeTargets.Method)]
    class ActionName : Attribute
    {
        public string URL { get; set; }
        public ActionName()
        {

        }
        public ActionName(string url)
        {
            this.URL = url;
        }
    }
特性類 HttpMethod
    [AttributeUsage(AttributeTargets.Method)]
    public class HttpMethod : Attribute
    {
        public Method method { get; set; }
        public HttpMethod()
        {
            this.method = Method.All;
        }

        public HttpMethod(Method _method)
        {
            this.method = _method;
        }

    }
特性類 FromApi
    [AttributeUsage(AttributeTargets.Class)]
    public class FromApi : Attribute
    {
        //窗體里的具體方法忽略
    }
幫助類 JsonHelper
    public static class JsonHelper
    {
        public static string GetJsonValue(string json, string key)
        {
            string value = "";
            if (string.IsNullOrEmpty(json)) { return ""; }
            JObject jo = (JObject)JsonConvert.DeserializeObject(json);
            if (jo.ContainsKey(key))
            {
                if (jo[key] != null)
                {
                    value = jo[key].ToString();
                }
            }
            return value;
        }
        public static List<string> GetJsonList(string json, string key)
        {
            List<string> value = new List<string>();
            if (string.IsNullOrEmpty(json)) { return new List<string>(); }
            JObject jo = (JObject)JsonConvert.DeserializeObject(json);
            if (jo.ContainsKey(key))
            {
                if (jo[key] != null)
                {
                    foreach (var item in jo[key])
                    {
                        value.Add(item.ToString());
                    }
                }
            }
            return value;
        }
    }

3.在Web.config中增加

  <appSettings>
    <add key="httpserver" value="127.0.0.1:8022"/>
  </appSettings>

4.使用方法

  • 4.1在窗體類上增加 [FromApi] 特性
    [FromApi]
    public partial class ScoketForm : Form
    {
        
    }
  • 4.2Program.cs 中增加 這種初始化方式會對程式集中所有帶有 [FromApi] 特性的類進行初始化
    Application.EnableVisualStyles();
    Application.SetCompatibleTextRenderingDefault(false);
    //服務初始化
    HttpApi.InitService();  //這裡是增加初始化的代碼
    Application.Run(new SocketTest.gg.ScoketForm());
  • 4.3具體使用方法 HttpMethod 後面可以不寫,不寫的話代表 支持兩種請求方式 POST,GET 需要註意命名空間的導入
        /// <summary>
        /// 方法說明
        /// </summary>
        /// <returns></returns>
        [HttpMethod(Method.Post), ActionName("/api/index")]
        public HttpResult Index(List<string> Ids)
        {

            HttpResult httpResult = new HttpResult();

            //具體方法內容
            return httpResult;
        }
如有疑問歡迎加入QQ群:765907694 交流!

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • js中的輪播圖案例: <!DOCTYPE html><html lang="en"> <head> <meta charset="utf-8"> <style type="text/css"> *{ margin: 0; padding: 0; } .box{ width: 800px; heigh ...
  • 一、邊距重疊常見情況 1、垂直方向上相鄰元素的重疊 (水平方向上不會發生重疊) 2、 垂直方向上父子元素間的重疊 二、BFC 1、什麼是 BFC BFC(Block Formatting Context),即塊級格式化上下文,創建了 BFC 的元素是一個獨立的容器,裡面無論如何佈局都不會影響到外面的 ...
  • meta元素有4個屬性:name、http-equiv、content、charset.meta標簽通過name屬性來表述頁面文檔的元信息,通過http-equiv屬性設置http請求指令,通過charset設置頁面的字元編碼。按照屬性設置分類,meta可以分為三類: name屬性和content屬 ...
  • 1. 什麼是對象? 對象object 是一些相關的變數和方法的軟體集。 特性: 屬性和方法 JavaScript中的所有事物都是對象。 創建對象的方法: 建立一個工廠函數 2.什麼是面向對象? 面向對象是一個思想,就是把解決問題的註意力集中到對象上。 面向對象的三大特點:封裝 繼承 多態。 封裝:把 ...
  • 前端項目優化 -Web 開發常用優化方案、Vue & React 項目優化 ...
  • 01. JavaScript的運行機制 (1)所有同步任務都在主線程上執行,形成一個執行棧。(2)主線程之外,還有一個“任務隊列”,只要非同步任務有了運行結果,就在“任務隊列”之中放置一個事件。(3)一旦“執行棧”中的所有同步任務執行完畢了,系統就會讀取“任務隊列”,看看裡面有哪些事件。那些對應的非同步 ...
  • 前言 今天沒有什麼前言,就是想分享些關於 的技術,任性。來吧,各位客官,裡邊請... 開篇第一問: 是什麼嘞? 首先咱們說哈,爬蟲不是“蟲子”,姑涼們不要害怕。 一種通過一定方式按照一定規則抓取數據的操作或方法。 開篇第二問: 能做什麼嘞? 來來來,談談需求 產品MM: 1. 愛豆的新電影上架了,整 ...
  • 微服務與K8S容器雲平臺架構微服務與12要素網路日誌收集服務網關服務註冊服務治理- java agent監控今天先到這兒,希望對技術領導力, 企業管理,系統架構設計與評估,團隊管理, 項目管理, 產品管理,團隊建設 有參考作用 , 您可能感興趣的文章: 領導人怎樣帶領好團隊構建創業公司突擊小團隊國際... ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...