QuickWebApi:使用Lambada方式,完成对WebApi的开发和调用。
QuickWebApi
目的:使用Lambada方式,完成对WebApi的开发和调用。
缘由:为了解耦服务和展现,将越来越多的使用WebApi提供各种服务;随着服务的细化,WebApi的接口将越来越多,成百上千。如何方便的管理和调用规模庞大的WebApi接口成了开发者头疼的问题。
设计:通过自定义的QuickWebApiAttribute来对业务接口进行规范和说明,并生成配置文件;可以通过修改配置文件,达成对WebApi的地址的调整而不用修改代码。
效果:除了重新搭建的系统可以使用外,对于一些其它语言(如java等)提供的webapi,只需要定义出相应的业务接口,便可以使用
原理:通过HttpClient类,使用Json作为请求和响应的数据格式实现。并通过定义相应的delegate,完成Lambada方式的调用,目前delegate只支持三个参数以内的接口(且参数类型目前仅支持int,long,string),如果超过三个参数或者其他的复杂类型,则应通过自定义对象的方式完成。
public delegate IHttpActionResult apiaction();
public delegate IHttpActionResult apiaction_l(long args);
public delegate IHttpActionResult apiaction_ll(long args1, long args2);
public delegate IHttpActionResult apiaction_li(long args1, int arg2);
public delegate IHttpActionResult apiaction_ls(long args1, string args2);
public delegate IHttpActionResult apiaction_i(int args1);
public delegate IHttpActionResult apiaction_ii(int args1, int args2);
public delegate IHttpActionResult apiaction_is(int args1, string args2);
public delegate IHttpActionResult apiaction_il(int args1, long args2);
public delegate IHttpActionResult apiaction_si(string args1, int args2);
public delegate IHttpActionResult apiaction_ss(string args1, string args2);
public delegate IHttpActionResult apiaction_sl(string args1, long args2);
public delegate IHttpActionResult apiaction_sss(string args1, string args2, string args3);
public delegate IHttpActionResult apiaction_o<treq>(treq data) where treq : class,new();
对于delegate的Lambada化和参数的传递解析实现:
result<tresp> _invoke_data<treq>(Expression exp, treq data) where treq : class
{
var method = ((exp as UnaryExpression).Operand as MethodCallExpression);
string code = ((method.Object as ConstantExpression).Value as MethodInfo).Name; foreach (var m in method.Arguments)
{
if (m.Type == typeof(T))
{
var attr = m.Type.GetCustomAttribute<QuickWebApiAttribute>();
if (attr != null)
{
return new invoker(build_server(attr.service)).Excute<tresp>(code, data);
}
}
}
return new result<tresp>(-1, "未能找到合适的api定义");
}
如果参数不是对象(需要注意的是,虽然处理了对DataTime类型的处理,但原则上不应出现该类型参数),则:
result<tresp> _invoke(Expression exp, params object[] args)
{
var method = ((exp as UnaryExpression).Operand as MethodCallExpression);
string code = ((method.Object as ConstantExpression).Value as MethodInfo).Name; foreach (var m in method.Arguments)
{
if (m.Type == typeof(T))
{
var attr = m.Type.GetCustomAttribute<QuickWebApiAttribute>();
StringBuilder sb = new StringBuilder();
var pis = m.Type.GetMethod(code).GetParameters(); for (int i = 0; i < pis.Length; i++)
{
sb.AppendFormat("{0}={1}&", pis[i].Name, args[i] is DateTime ? ((DateTime)args[i]).ToString("yyyy-MM-dd HH:mm:ss") : args[i]);
} if (attr != null)
{
return new invoker(build_server(attr.service)).Excute<tresp>(code, sb.ToString());
}
}
}
return new result<tresp>(-1, "未能找到合适的api定义");
}
以上是WebApi访问Lambada化的核心代码块。如需了解更多,在文章结尾有我的源码地址连接。
接下来介绍一下QuickWebApi在实际开发过程中的使用,包括接口服务端和接口调用端的样例代码。
服务业务接口及模型设计:
//数据模型
public class customer
{
public int id { get; set; }
public long timestamp { get; set; }
public string name { get; set; }
public int age { get; set; }
public DateTime birthday { get; set; }
public bool state { get; set; }
}
//业务接口动态库声明
[assembly: QuickWebApiDll("customer", "http://localhost:11520")]
//业务接口声明,接口中的返回值为IHttpActionResult,以便更好的处理HTTP响应
[QuickWebApi("customer", "api/customer_service", "用户管理")]
public interface icustomer
{
[QuickWebApi(MethodType.HTTPGET, "用户列表", "列举用户信息")]
IHttpActionResult list();
[QuickWebApi(MethodType.HTTPGET)]
IHttpActionResult info(int customerid);
[QuickWebApi(MethodType.HTTPPOST)]
IHttpActionResult update(int id, string name);
[QuickWebApi(MethodType.HTTPDEL)]
IHttpActionResult del(int id);
[QuickWebApi(MethodType.HTTPPUT)]
IHttpActionResult save(customer customer);
}
//业务接口实现,设置路由机制
[Route("api/customer_service/{action}/")]
public class customerController : ApiController, icustomer
{
[HttpGet]
public IHttpActionResult list()
{
return Ok(new result(0, null, DB.customers.ToList().Count, DB.customers.ToList()));
} [HttpGet]
public IHttpActionResult info(int customerid)
{
return Ok(new result(DB.customers.SingleOrDefault(c => c.id == customerid)));
} [HttpPost]
public IHttpActionResult update(int id, string name)
{
var cust = DB.customers.SingleOrDefault(c => c.id == id);
cust.name = name;
return Ok(new result());
} [HttpDelete]
public IHttpActionResult del(int id)
{
DB.customers.RemoveAll(c => c.id == id);
return Ok(new result());
} [HttpPut]
public IHttpActionResult save(customer customer)
{
DB.customers.RemoveAll(c => c.id == customer.id);
DB.customers.Add(customer);
return Ok(new result());
}
}
调用端相应的配置和加载:
//在服务启动时调用,一般在global中
webapifactory.Instance.Build_Apis();
webapifactory.Instance.Load_Apis(); //配置文件格式(*.xml)如下(每个业务接口生成一个独立的配置文件,便于维护):
<?xml version="1.0" encoding="utf-16"?>
<ArrayOfWebApiNode xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<WebApiNode>
<Name>用户管理</Name>
<Title>QuickWebApi.Sample.Apis</Title>
<Version>1.0.0.0</Version>
<Service>customer</Service>
<Route>api/customer_service</Route>
<Uri>http://localhost:11520</Uri>
<Actions>
<WebApiMethod>
<Method>HTTPGET</Method>
<Action>list</Action>
<Name>用户列表</Name>
<Comment>列举用户信息</Comment>
</WebApiMethod>
<WebApiMethod>
<Method>HTTPGET</Method>
<Action>info</Action>
</WebApiMethod>
<WebApiMethod>
<Method>HTTPPOST</Method>
<Action>update</Action>
</WebApiMethod>
<WebApiMethod>
<Method>HTTPDEL</Method>
<Action>del</Action>
</WebApiMethod>
<WebApiMethod>
<Method>HTTPPUT</Method>
<Action>save</Action>
</WebApiMethod>
</Actions>
</WebApiNode>
</ArrayOfWebApiNode> //并同时生产简单的业务接口描述文件(*.txt):
001,用户管理:QuickWebApi.Sample.Apis-1.0.0.0-
001,http://localhost:11520/api/customer_service/list,用户列表,列举用户信息
002,http://localhost:11520/api/customer_service/info,,
005,http://localhost:11520/api/customer_service/update,,
006,http://localhost:11520/api/customer_service/del,,
008,http://localhost:11520/api/customer_service/save,,
调用端使用方式
public class HomeController : Controller
{
public object customers()
{
var ret = new webapi<icustomer>().invoke(i => i.list);
return ret;
}
public JsonResult customer_list()
{
var ret = new webapi<icustomer, List<customer>>().invoke(i => i.list);
List<object> custs = new List<object>();
foreach (var cust in ret.data)
{
custs.Add(new { id = cust.id, name = cust.name, age = cust.age });
}
return Json(custs, JsonRequestBehavior.AllowGet);
}
public object info()
{
var ret = new webapi<icustomer>().invoke(i => i.info, 4);
return ret;
}
public object update()
{
var ret = new webapi<icustomer>().invoke(i => i.update, 3, "new name");
return ret;
}
public object save()
{
var cust = new customer() { id = 3, name = "new name", age = 22, timestamp = DateTime.Now.Ticks, birthday = DateTime.Now.AddYears(-10) };
var ret = new webapi<icustomer>().invoke(i => i.save, cust);
return ret;
}
public object delete()
{
var ret = new webapi<icustomer>().invoke(i => i.del, 4);
return ret;
}
}
其它说明及注意事项:
//invoke方法的返回结果的数据结构如下:
public class result<T> where T : class, new()
{
//如果通讯不正常,则为返回的HTTP状态吗;否则为服务端返回的状态吗,默认值为0(正常)
public int errcode { get; set; }
//服务端返回的信息
public string errmsg { get; set; }
//服务端返回的复杂数据结构,通过Json进行传输
public T data { get; set; }
//如果需要返回整型
public long id { get; set; }
//服务器端时间
public DateTime time { get; set; }
}
//如果页面上通过ajax直接调用WebApi接口,则需要在服务端注册JsonFormatter,则ajax可以直接得到result的json格式:
public static void Register(HttpConfiguration config)
{
// Web API configuration and services
webapifactory.Instance.Register_JsonFormatter(config); // Web API routes
config.MapHttpAttributeRoutes(); config.Routes.MapHttpRoute(
name: "DefaultApi",
routeTemplate: "api/{controller}/{id}",
defaults: new { id = RouteParameter.Optional }
); }
感谢您的阅读。源码
目前QuickWebApi还有一些其它想法和设计会未加入其中,后续会继续修缮。且还存在一些未解决的问题,欢迎您能贡献您的智慧和意见。
QuickWebApi:使用Lambada方式,完成对WebApi的开发和调用。的更多相关文章
- QuickWebApi2:使用Lambda方式,完成对WebApi的开发和调用-文档的生成
续 QuickWebApi:使用Lambda方式,完成对WebApi的开发和调用 上一篇完成了主要的功能,本次修订主要重构了对接口文档的生成规范,使之可读性更佳,甚至可以作为接口文档进行发布(当然,在 ...
- c# WebApi创建及客户端调用
前段时间学习WebApi的创建与调用,网上的信息千奇百怪(知识有限,看不懂啊),通过查阅资料及借鉴博友实例分析后总结一下,总结一套简单完整的WebApi创建及实例 首先创建一个WebApi服务(流程就 ...
- Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行(含系列目录)。
前言: Taurus.MVC 微服务版本已经发布了:Taurus.MVC V3.0.3 微服务开源框架发布:让.NET 架构在大并发的演进过程更简单. 以前都是框架发布时写点相关功能点的文章,没有形成 ...
- Taurus.MVC WebAPI 入门开发教程4:控制器方法及参数定义、获取及基础校验属性【Require】。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
- Taurus.MVC WebAPI 入门开发教程5:控制器安全校验属性【HttpGet、HttpPost】【Ack】【Token】【MicroService】。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
- Taurus.MVC WebAPI 入门开发教程6:全局控制器DefaultController与全局事件。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
- JAX-RS 方式的 RESTful Web Service 开发
JAX-RS 方式的 RESTful Web Service 开发 ——基于 CXF+Spring 的实现 Web Service 目前在风格上有两大类,一个是基于 SOAP 协议,一个是完全遵循 H ...
- Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
- Taurus.MVC WebAPI 入门开发教程3:路由类型和路由映射。
系列目录 1.Taurus.MVC WebAPI 入门开发教程1:框架下载环境配置与运行. 2.Taurus.MVC WebAPI 入门开发教程2:添加控制器输出Hello World. 3.Tau ...
随机推荐
- javascript中对字符串的操作总结
原文:javascript中对字符串的操作总结 没听过一句话吗?程序员的世界,不处理字符串就是处理数组.这是群里的一位前辈和我说的,显然这和我之前理解的DOM是javascript的核心的不同的,看了 ...
- 使用SharePoint创建和定义自己的网站页面
使用SharePoint创建和定义自己的网站页面 1. 打开SharePoint Designer 2010. 2. 点击网站页面导航. 3. 在功能区点击Web部件页面,新建Employee.axp ...
- cocos2dx 3.0 它 使用std::bind更换CC_CALLBACK_N
在cocos2dx 3.0 版本号,回调函数本质4一个CC_CALLBACK_N 替换功能.N的回调函数的参数的数量的代表 1.让我们来看看这些CC_CALLBACK_N怎么用 比方action的回调 ...
- 【百度地图API】如何进行地址解析与反地址解析?——模糊地址能搜索到精确地理信息!
原文:[百度地图API]如何进行地址解析与反地址解析?--模糊地址能搜索到精确地理信息! 摘要: 什么是地址解析? 什么是反地址解析? 如何运用地址解析,和反地址解析? 可以同时运用地址解析,和反地址 ...
- C语言练手自己编写学生成绩管理系统
#include<stdio.h> #include<stdlib.h> /*定义学生结构体*/ struct Student { ]; ]; float Mark1; flo ...
- DbModel
DbModel 前言 我们都知道EF可以生成Dbmodel,系统生成的Model有时候并不是我们想要的,如何我们要生成自己的Model,那么久需要我们手动的去修改T4模版,T4是对“Text Temp ...
- Web API 2:Action的返回类型
Web API 2:Action的返回类型 Web API控制器中的Action方法有如下几种返回类型: void HttpResponseMessage IHttpActionResult 其它类型 ...
- Cocos2d-x3.0之路--02(引擎文件夹分析和一些细节)
关于怎么搭建好开发环境的我就不写了,网上非常多. 那么 我们来看看 引擎文件的文件夹 所谓知己知彼 百战不殆嘛 先说一下setup.py 这个文件是有关配置的python文件,比方我们在进行andro ...
- struts2文件下载 <result type="stream">
<!--struts.xml配置--> <action name="download" class="com.unmi.action.DownloadA ...
- 一个大浪Java罢工(一个)安装JDK和环境变量配置
一个.基础知识 (一)什么是Java? Java是一种能够撰写跨平台应用软件的面向对象的程序设计语言,是由Sun Microsystems公司于1995年5月推出的Java程序设计语言和Java平台( ...