优雅的在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; }
赞 (0)