优雅的在WinForm/WPF/控制台 中使用特性封装WebApi
程序员文章站
2022-07-10 21:39:29
优雅的在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 start() { // 获取完全名称 string classname = new stacktrace().getframe(1).getmethod().reflectedtype.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(); //参数 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; } }
帮助类 jsonhelp
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在load事件最后一行中增加
httpapi.start();
- 4.2具体使用方法 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 交流!
上一篇: 如何理解类?