利用委托与Lambada创建和调用webapi接口
前言
现在项目中用的是webapi,其中有以下问题:
1.接口随着开发的增多逐渐增加相当庞大。
2.接口调用时不好管理。
以上是主要问题,对此就衍生了一个想法:
如果每一个接口都一个配置文件来管理,每个配置文件能清晰表示处理接口文件,地址,参数,返回值,那么通过这个配置文件,就能很好的管理起来我们所有的webapi接口不是吗?
有了这个思路之后就有了以下的实现:
1.具体实现:
public void Build_Apis()
{
))
{
var vatt = ass.GetCustomAttribute<AssemblyFileVersionAttribute>();
var tatt = ass.GetCustomAttribute<AssemblyTitleAttribute>();
var datt = ass.GetCustomAttribute<QuickWebApiDllAttribute>();
apis.Clear();
var input_types = new List<Type>();
foreach (var type in ass.GetTypes())
{
var attr = type.GetCustomAttribute<QuickWebApiAttribute>();
if (attr != null)
{
WebApiNode api = new WebApiNode(datt.Domain) { Name = attr.name, Service = attr.service, Route = attr.route, Comment = attr.comment, Version = vatt.Version, Title = tatt.Title };
foreach (var mi in type.GetMethods())
{
var att = mi.GetCustomAttribute<QuickWebApiAttribute>();
if (att != null)
{
var act = new WebApiMethod() { Action = mi.Name, Code = att.service, Method = att.methodtype, Name = string.IsNullOrWhiteSpace(att.name) ? mi.Name : att.name, Comment = att.comment, OutputType = att.resultype };
foreach (var arg in mi.GetParameters())
{
var mdatt = arg.ParameterType.GetCustomAttribute<DescriptionAttribute>();
act.Params.Add(new WebApiMethodParam() { Name = arg.Name, TypeName = arg.ParameterType.Name, DefaultValue = string.IsNullOrWhiteSpace(arg.DefaultValue.ToString()) ? "无默认值" : arg.DefaultValue.ToString(), Desc = mdatt == null ? "" : mdatt.Description });
if (arg.ParameterType.IsClass && arg.ParameterType != typeof(string))
{
if (!input_types.Exists(t => t.Name == arg.ParameterType.Name))
input_types.Add(arg.ParameterType);
}
}
if (!api.Methods.Exists(a => a.Action == act.Action))
api.Methods.Add(act);
if (att.resultype != null && att.resultype.IsClass && att.resultype != typeof(string))
{
if (!input_types.Exists(t => t.Name == att.resultype.Name))
input_types.Add(att.resultype);
}
}
}
if (!apis.Exists(a => a.Service == api.Service))
apis.Add(api);
}
}
Build_Apids_Config(apis, datt.Name);
Build_Apids_Doc(apis, datt.Name, input_types);
}
}
1.1:其中Build_Apis()方法,是系统根据,webapi接口描述,创建的对应的接口服务配置文件操作。
配置如下:
生成接口文件如下:
接口的实现
接下来只需你把xml文件引用到你要调用的站点下即可。
public string Load_Apis()
{
var files = System.IO.Directory.GetFiles(AppDomain.CurrentDomain.BaseDirectory, "apis_*.xml", System.IO.SearchOption.AllDirectories);
apis.Clear();
foreach (var path in files)
{
var jss = System.IO.File.ReadAllText(path);
var _apis = Deserialize<List<WebApiNode>>(jss);
) continue;
foreach (var api in _apis)
{
if (apis.Exists(a => a.Service == api.Service)) continue;
apis.Add(api);
}
}
return string.Format("service:{0}, action:{1}", apis.Count, apis.Sum(a => a.Methods.Count));
}
1.2:其中Load_Apis()方式是在程序启动时加载webapi服务配置文件的操作,在这不再累述。
public class webapi<T, tresp> where tresp : class,new()
{
public webapi() { }
public webapi(string service_prefix)
{
_service_prefix = service_prefix;
}
public webapi(long service_prefix_id)
{
_service_prefix = service_prefix_id.ToString();
}
protected string build_server(string srv)
{
return string.IsNullOrWhiteSpace(_service_prefix) ? srv : string.Format("{0}_{1}", _service_prefix, srv);
}
string _service_prefix;
public result<tresp> invoke(Expression<Func<T, apiaction_l>> func, long args1)
{
return _invoke(func.Body, args1);
}
public result<tresp> invoke(Expression<Func<T, apiaction_ll>> func, long args1, long args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_li>> func, long args1, int args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_ls>> func, long args1, string args2)
{
return _invoke(func.Body, args1, args2);
}
//public result<tresp> invoke<treq>(Expression<Func<T, apiaction_s<treq>>> func, treq args1) where treq : struct
//{
// return _invoke(func.Body, args1);
//}
public result<tresp> invoke(Expression<Func<T, apiaction_i>> func, int args1)
{
return _invoke(func.Body, args1);
}
public result<tresp> invoke(Expression<Func<T, apiaction_ii>> func, int args1, int args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_il>> func, int args1, long args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_is>> func, int args1, string args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_ss>> func, string args1, string args2)
{
return _invoke(func.Body, args1, args2);
}
public result<tresp> invoke(Expression<Func<T, apiaction_sss>> func, string args1, string args2, string args3)
{
return _invoke(func.Body, args1, args2, args3);
}
public result<tresp> invoke<treq>(Expression<Func<T, apiaction_o<treq>>> func, treq data) where treq : class,new()
{
if (data != null && data is String)
{
return _invoke(func.Body, data);
}
return _invoke_data<treq>(func.Body, data);
}
public result<tresp> invoke(Expression<Func<T, apiaction>> func)
{
return _invoke_data<object>(func.Body, null);
}
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);
}
}
}
, "未能找到合适的api定义");
}
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();
; 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());
}
}
}
, "未能找到合适的api定义");
}
}
1.3:其中 result<tresp> _invoke是:通过lambda对传递过来的委托,进行相应的反射操作。
其中委托定义如下:
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只支持三个参数以内的接口(且参数类型目前仅支持int,long,string),如果参数不符合条件可传递对象。
以上为具体实现至于有不了解的可以在文章顶部下载代码也可以,点击公共中qq与我联系。
2.下面我来写一下它的使用:
2.1.初始化:
在global中添加如下代码:
2.2.在mvc中调用:
利用委托与Lambada创建和调用webapi接口的更多相关文章
- WebApi接口 - 如何在应用中调用webapi接口
很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...
- 如何使用程序调用webApi接口
如何使用程序调用webApi接口 在C#中,传统调用HTTP接口一般有两种办法: WebRequest/WebResponse组合的方法调用 WebClient类进行调用. 第一种方法抽象程度较低,使 ...
- php中创建和调用webservice接口示例
php中创建和调用webservice接口示例 这篇文章主要介绍了php中创建和调用webservice接口示例,包括webservice基本知识.webservice服务端例子.webservi ...
- aspx页面调用webapi接口报错:远程服务器返回错误:(500)内部服务器错误
代码在运行到response = (HttpWebResponse)request.GetResponse();就开始报错 原因:可能因为所调用的接口不存在或者接口中存在错误,可用postman测试接 ...
- 【C#】 创建和调用webapi
二,,通过普通的路由调用,,路径写到http://localhost:29920/api/Players 即 Api/controller 为止
- 使用httpclient异步调用WebAPI接口
最近的工作需要使用Bot Framework调用原有的WebAPI查询数据,查找了一些方法,大部分都是使用HttpClient调用的,现时贴出代码供参考 using System; using Sys ...
- 使用HttpClient调用WebAPI接口,含WebAPI端示例
API端: using log4net; using System; using System.Collections.Generic; using System.IO; using System.L ...
- 调用WebAPI接口地址返回序列化的JSON对象中的属性都加了个k__BackingField关键字的解决办法
1.问题现象: 2.造成此问题的原因是返回的结果对象实体上面加了个可序列号特效 [Serializable].去掉就可以了. 3.解决后的效果:
- WebApi(6) 后台C#调用WebApi
https://www.cnblogs.com/cxd1008/p/6640015.html 今天来写一下后台C#代码如何访问webapi 这里使用HttpClient方法访问webapi也是很常用的 ...
随机推荐
- C++异常处理
引言 异常,让一个函数可以在发现自己无法处理的错误时抛出一个异常,希望它的调用者可以直接或者间接处理这个问题.而传统错误处理技术,检查到一个局部无法处理的问题时: 1.终止程序(例如atol,atoi ...
- 更改UIsearchbar 的背景和cancel按钮(转)
修改背景 searchbar =[[UISearchBar alloc]initWithFrame:CGRectMake(,KTopBarHeight, , KTopBarHeight)]; sear ...
- linux/ubuntu查看内核版本命令
打开终端,输入: uname -a
- python模块(六)
模块,用一砣代码实现了某个功能的代码集合. 类似于函数式编程和面向过程编程,函数式编程则完成一个功能,其他代码用来调用即可,提供了代码的重用性和代码间的耦合.而对于一个复杂的功能来,可能需要多个函数才 ...
- [转]js获取域名、url、url参数值
//获取域名host1 = window.location.host;host2 = document.domain; //获取页面完整地址url = window.location.href; 获取 ...
- CFBundleVersion与CFBundleShortVersionString,上架注意事项
CFBundleVersion,标识(发布或未发布)的内部版本号.这是一个单调增加的字符串,包括一个或多个时期分隔的整数. CFBundleShortVersionString 标识应用程序的发布版 ...
- .net core
- centos 7.0 nginx 1.7.9成功安装过程
centos 7.0根目录 的目录构成 [root@localhost /]# lsbin dev home lib64 mnt proc run srv tmp varboot etc lib me ...
- windows7下修改hosts文件无效解决办法(转)
通常会为了开发方便.或者屏蔽掉一些恶意网站,我们会在hosts(c:\windows\system32\drivers\etc\hosts)文件中进行相应的域名指向,例:
- PHP常用数据库代码汇总
连接MYSQL //MYSQL数据库配置 define(DB_HOST, '127.0.0.1'); define(DB_USER, 'user'); define(DB_PASS, 'pass'); ...