前言 

 现在项目中用的是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接口的更多相关文章

  1. WebApi接口 - 如何在应用中调用webapi接口

    很高兴能再次和大家分享webapi接口的相关文章,本篇将要讲解的是如何在应用中调用webapi接口:对于大部分做内部管理系统及类似系统的朋友来说很少会去调用别人的接口,因此可能在这方面存在一些困惑,希 ...

  2. 如何使用程序调用webApi接口

    如何使用程序调用webApi接口 在C#中,传统调用HTTP接口一般有两种办法: WebRequest/WebResponse组合的方法调用 WebClient类进行调用. 第一种方法抽象程度较低,使 ...

  3. php中创建和调用webservice接口示例

    php中创建和调用webservice接口示例   这篇文章主要介绍了php中创建和调用webservice接口示例,包括webservice基本知识.webservice服务端例子.webservi ...

  4. aspx页面调用webapi接口报错:远程服务器返回错误:(500)内部服务器错误

    代码在运行到response = (HttpWebResponse)request.GetResponse();就开始报错 原因:可能因为所调用的接口不存在或者接口中存在错误,可用postman测试接 ...

  5. 【C#】 创建和调用webapi

    二,,通过普通的路由调用,,路径写到http://localhost:29920/api/Players  即   Api/controller  为止

  6. 使用httpclient异步调用WebAPI接口

    最近的工作需要使用Bot Framework调用原有的WebAPI查询数据,查找了一些方法,大部分都是使用HttpClient调用的,现时贴出代码供参考 using System; using Sys ...

  7. 使用HttpClient调用WebAPI接口,含WebAPI端示例

    API端: using log4net; using System; using System.Collections.Generic; using System.IO; using System.L ...

  8. 调用WebAPI接口地址返回序列化的JSON对象中的属性都加了个k__BackingField关键字的解决办法

    1.问题现象: 2.造成此问题的原因是返回的结果对象实体上面加了个可序列号特效 [Serializable].去掉就可以了. 3.解决后的效果:

  9. WebApi(6) 后台C#调用WebApi

    https://www.cnblogs.com/cxd1008/p/6640015.html 今天来写一下后台C#代码如何访问webapi 这里使用HttpClient方法访问webapi也是很常用的 ...

随机推荐

  1. 1125MySQL Sending data导致查询很慢的问题详细分析

    -- 问题1 tablename使用主键索引反而比idx_ref_id慢的原因EXPLAIN SELECT SQL_NO_CACHE COUNT(id) FROM dbname.tbname FORC ...

  2. CodeForces 548D 单调栈

    Mike and Feet Time Limit:1000MS     Memory Limit:262144KB     64bit IO Format:%I64d & %I64u Subm ...

  3. 配置windows 系统PHP系统环境变量

    1. 首先到php官网下载php-5.3.6-nts-Win32-VC9-x86.ZIP 解压到电脑硬盘.将文件解压到文件夹php5.3.6下载地址:http://www.php.net/downlo ...

  4. npm 使用记录

    在 Mint 下安装 pencil,折腾半天,发现它对 firefox 的支持,只到 46.0 .本来打算研究下怎么用 xulrunner 来跑 pencil 这个 web 应用,查看项目资源的时候, ...

  5. Alpha阶段测试报告

    测试说明 APP中前后端交互的接口主要有两种,一种是游戏开始前获取信息的HTTP请求接口,这种接口可以看成是静态的,比较简单:另外一种就是游戏过程中进行实时通信的Websocket请求接口,因为这是在 ...

  6. C#操作剪贴板

    操作剪贴版,主要用到了ClipBoard类. 该类位于 System.Windows(WPF)或System.Windows.Forms(Winform)下. 1.设置内容到剪贴版上: 主要用到Cli ...

  7. BZOJ4567[Scoi2016]背单词

    4567: [Scoi2016]背单词 Time Limit: 10 Sec Memory Limit: 256 MB Submit: 304 Solved: 114 [Submit][Status] ...

  8. Java排序算法——基数排序

  9. 将javascript函数写在Html标签里

    有些时候不想把函数写在script标签里了,想直接在html标签里直接加上js代码,可以这样写: <body onload="javascript:{window.location.h ...

  10. .Net创建windows服务入门

    本文主要记录学习.net 如何创建windows服务. 1.创建一个Windows服务程序 2.新建安装程序 3.修改service文件 代码如下 protected override void On ...