日常开发中经常会用到接口,传输都基于http,.net下有简单的ashx或aspx等搭载接口或MVC下的WebApi,或Wcf等。。
之前开发中用到了Web轻型框架:Nancy,Json序列化工具ServiceStack.Text,于是将两者结合下构造一个我自己的小接口框架
一.服务端抽象
先上5个基本抽象类和接口
1.请求基类:可包含一些账户等信息
public class RequestBase { }
2.响应基类:包括响应状态
public class ResponseBase { public ResponseBase() { Status = new ResponseStatus(); } public ResponseStatus Status { get; set; } }
public class ResponseStatus { public ResponseStatus() { this.ErrCode = string.Empty; this.ErrMsg = string.Empty; } public ResponseStatus(string errCode, string errMsg) { this.ErrCode = errCode; this.ErrMsg = errMsg; } /// <summary> /// 是否成功 /// </summary> public bool IsSuccess { get { if (string.IsNullOrEmpty(ErrCode) || string.IsNullOrEmpty(ErrMsg)) { return true; } else { return false; } } } /// <summary> /// 错误码 /// </summary> public string ErrCode { get; set; } /// <summary> /// 错误信息 /// </summary> public string ErrMsg { get; set; } }
3.接口验证接口:验证请求参数等
public interface IBaseService<R, S> where R : RequestBase where S : ResponseBase { /// <summary> /// 请求验证 /// </summary> /// <param name="request">请求实体</param> /// <returns></returns> ResponseStatus Vaild(R request); }
4.接口逻辑处理接口:处理核心逻辑
public interface ICoreService<R, S> where R : RequestBase where S : ResponseBase { S GetResponse(R r); }
最终一个接口的请求验证——处理流程变成了这样:
public class ServiceClient { public static S Excute<R, S>(R r, IBaseService<R, S> baseService, ICoreService<R, S> coreService) where R : RequestBase where S : ResponseBase { S s = System.Activator.CreateInstance<S>(); try { s.Status = baseService.Vaild(r); if (s.Status.IsSuccess) { s = coreService.GetResponse(r); } } catch (Exception ex) { s.Status = new ResponseStatus("0", "接口内部异常" + ex.Message); } return s; } }
以上是接口服务端抽象出来的各个部分
二.接口Host:包括接口部署寄存的web以及Url规则和反射
Host采用Nancy框架,主要有两个路由:
Post["{Service}/{Request}"] = p => { ErrResponse errResponse = new ErrResponse(); try { string reqName = p.Request.ToString().ToLower().Trim(); string serviceName = p.Service.ToString().ToLower().Trim(); if (!Config.ServiceTypeList.ContainsKey(serviceName) || !Config.RequestTypeList.ContainsKey(reqName)) { errResponse.Status = new ResponseStatus("0", "无此接口"); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } Type request = Config.RequestTypeList[reqName]; Type response = Config.ResponseTypeList[reqName]; Type service = Config.ServiceTypeList[serviceName]; object req = JsonSerializer.DeserializeFromStream(request, Request.Body); if (req == null) { errResponse.Status = new ResponseStatus("0", "请求参数不能为空或格式错误"); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } object res = Config.DelegateList[reqName](req);//直接缓存委托 return JsonSerializer.SerializeToString(res, response); } catch (Exception ex) { errResponse.Status = new ResponseStatus("0", "接口内部异常" + ex.Message); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } }; Get["{Service}/{Request}"] = p => { ErrResponse errResponse = new ErrResponse(); try { string reqName = p.Request.ToString().ToLower().Trim(); string serviceName = p.Service.ToString().ToLower().Trim(); if (!Config.ServiceTypeList.ContainsKey(serviceName) || !Config.RequestTypeList.ContainsKey(reqName)) { errResponse.Status = new ResponseStatus("0", "无此接口"); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } Type request = Config.RequestTypeList[reqName]; Type response = Config.ResponseTypeList[reqName]; Type service = Config.ServiceTypeList[serviceName]; string strReq = Request.Query["request"]; object req = JsonSerializer.DeserializeFromString(strReq, request); if (req == null) { errResponse.Status = new ResponseStatus("0", "请求参数不能为空或格式错误"); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } object res = Config.DelegateList[reqName](req);//直接缓存委托效率更高 return JsonSerializer.SerializeToString(res, response); } catch (Exception ex) { errResponse.Status = new ResponseStatus("0", "接口内部异常" + ex.Message); return JsonSerializer.SerializeToString<ErrResponse>(errResponse); } };
一个Get,一个Post处理逻辑是一样的,本来想分开,后来没什么时间,
Nancy部分可以参考开源项目:https://github.com/NancyFx/Nancy
这里主要讲下
1.路由:"{Service}/{Request}"根据不同的Service以及不同的Request获取对应的Type,接口在启动时已将所有Service以及请求,响应的Type做了缓存,还有处理方法(后面讲)
2.Json序列化:ServiceStack.Text
3.初始化缓存:
public class Config { public static Dictionary<string, Type> RequestTypeList = new Dictionary<string, Type>(); public static Dictionary<string, Type> ResponseTypeList = new Dictionary<string, Type>(); public static Dictionary<string, Type> ServiceTypeList = new Dictionary<string, Type>(); //public static Dictionary<string, MethodInfo> MethodInfoList = new Dictionary<string, MethodInfo>(); public static Dictionary<string, DoService> DelegateList = new Dictionary<string, DoService>(); public static void Init() { if (RequestTypeList.Count > 0) { return; } EntityClient.AddToDomain(); Assembly[] ass = AppDomain.CurrentDomain.GetAssemblies(); Assembly entitysAss = ass.Where(t => t.FullName.Contains("FaceManage.Entitys")).FirstOrDefault(); Assembly serviceAss = ass.Where(t => t.FullName.Contains("FaceManage.Services")).FirstOrDefault(); List<Type> reqTypes = entitysAss.GetTypes().Where(t => t.BaseType == typeof(RequestBase)).ToList(); List<Type> resTypes = entitysAss.GetTypes().Where(t => t.BaseType == (typeof(ResponseBase))).ToList(); List<Type> serviceTypes = serviceAss.GetTypes().Where(t => t.BaseType == typeof(ServiceBase)).ToList(); foreach (Type item in reqTypes) { RequestTypeList.Add(item.Name.Replace("Request", "").ToLower().Trim(), item); } foreach (Type item in resTypes) { ResponseTypeList.Add(item.Name.Replace("Response", "").ToLower().Trim(), item); } foreach (Type item in serviceTypes) { ServiceTypeList.Add(item.Name.Replace("Service", "").ToLower().Trim(), item); MethodInfo[] methods = item.GetMethods(BindingFlags.Public | BindingFlags.Static); foreach (MethodInfo method in methods) { DoService serviceDelegate = (DoService)Delegate.CreateDelegate(typeof(DoService), null, method); DelegateList.Add(method.Name.ToLower().Trim(), serviceDelegate); //MethodInfoList.Add(method.Name, method); } } } }
这里我们知道接口符合一个委托,
public delegate object DoService(object request);
刚刚说到缓存方法就是创建方法的委托,并进行缓存,效率较高
MethodInfo[] methods = item.GetMethods(BindingFlags.Public | BindingFlags.Static); foreach (MethodInfo method in methods) { DoService serviceDelegate = (DoService)Delegate.CreateDelegate(typeof(DoService), null, method); DelegateList.Add(method.Name.ToLower().Trim(), serviceDelegate); //MethodInfoList.Add(method.Name, method); }
三。创建一个接口
1.请求:
public class UpdateMemberTypeRequest : RequestBase { public int MemberId { get; set; } public int MemberType { get; set; } }
2.响应:
public class UpdateMemberTypeResponse : ResponseBase { public bool IsSuccess { get; set; } }
3.验证服务:
public class UpdateMemberTypeBase : IBaseService<UpdateMemberTypeRequest, UpdateMemberTypeResponse> { public ResponseStatus Vaild(UpdateMemberTypeRequest request) { ResponseStatus status = new ResponseStatus(); try { if (request.MemberId <= 0) { throw new Exception("会员Id不能小于0"); } } catch (Exception ex) { status.ErrCode = "0"; status.ErrMsg = ex.Message; } return status; } }
4.处理逻辑:
public class UpdateMemberTypeCore : ICoreService<UpdateMemberTypeRequest, UpdateMemberTypeResponse> { public UpdateMemberTypeResponse GetResponse(UpdateMemberTypeRequest request) { UpdateMemberTypeResponse response = new UpdateMemberTypeResponse(); UpdateMemberTypeModel model = UpdateMemberTypeModel.Init(request); response.Status = model.UpdateMemberType(); if (response.Status.IsSuccess) { response.IsSuccess = true; } return response; } }
5.一行代码
public static object UpdateMemberType(object req) { UpdateMemberTypeRequest request = (UpdateMemberTypeRequest)req; return ServiceClient.Excute<UpdateMemberTypeRequest, UpdateMemberTypeResponse>(request, new UpdateMemberTypeBase(), new UpdateMemberTypeCore()); }
这样一个接口就开发Ok,
当然还忘了一点,这个时候其实你已经完成建立你自己接口的SDK
public static T Excute<T, S>(S req, string url) { T rsp = Activator.CreateInstance<T>(); string reqJson = JsonSerializer.SerializeToString<S>(req); string resJson = HttpHelper.DoPost(url, reqJson, Encoding.UTF8); return JsonSerializer.DeserializeFromString<T>(resJson); }
调用方:
AddCooperaterRequest request = new AddCooperaterRequest() { Name = "test", PassWord = "test" }; AddCooperaterResponse response = EntityClient.Excute<AddCooperaterResponse, AddCooperaterRequest>(request, "http://localhost/FaceManage/BaseMember/AddCooperater");
原项目将过几天开源
原文:http://www.cnblogs.com/isingel/p/3892717.html