• 借助委托和反射 统一客户端调用入口


    反射:反射是相当强大的一个机制,它允许在运行时发现并使用编译时还不了解的类型及其成员;

    委托:System.Delegate提供了几个方法,在编译时不知道委托的某些必要信息时,利用本身提供的几个方法创建并调用一个委托,CreateDelegate、DynamicInvoke。

    在做MVC项目或者WebAPI项目时,经常会遇到JS和后台动态交互的情况,按照以前的逻辑是每个请求对应不同的URL(即不同的后台Action),久而久之造成很难维护的局面,让人尴尬万分,

      $.get("/Home/Action4", { item1: "1" }, function (data) {
            alert(data);
        });
    
      $.get("/Home/Action3", { item1: "2" }, function (data) {
            alert(data);
        });
    
    
      $.get("/Home/Action2", { item1: "3" }, function (data) {
            alert(data);
        });
    
    
      $.get("/Home/Action1", { item1: "4" }, function (data) {
            alert(data);
        });
    

     每个页面有几个交互,不同的页面又有很多不同的交互,每个模块。。。。。。。

    但是现在借助伟大的.net平台提供的反射和委托机制,我们终于可以改变这种混乱的局面,统一前端和后台数据交互的入口:

    优势自不必说,下面是一个测试案例:

    前端Ajax请求部分:

    <script type="text/javascript">
        $.get("/Home/DynamicEnvoke", { item1: "NumChars|OneString|4362846327846328" }, function (data) {
            alert(data);
        });
        $.get("/Home/DynamicEnvoke", { item1: "SubTract|TwoInt32s|2|1" }, function (data) {
            alert(data);
        });
    </script>
    

     既然是统一入口,所以可以看到URL不再变化,变化的只是传入的参数,每个参数用|分隔,至于客户端的URL可以封装成常量或其他办法。

    DynamicEnvoke是什么? 一个后台的入口Public的方法,传递的参数仅仅是一个字符串类型的参数,这里可以重写Model绑定机制来支持更高级的模型类型(如数组、集合、字典,复杂类型,具体参考
    通过实例模拟ASP.NET MVC的Model绑定机制:数组系列文章):

       public object DynamicEnvoke(string item1)
            {
                var args = item1.Split('|');
    
                Type deltype = Type.GetType(args[1]);
                if (deltype == null)
                {
                    Console.WriteLine("invalid deltype args");
                    return null;
                }
                Delegate del = null;
                try
                {
                    var mi = typeof(HomeController).GetMethod(args[0], BindingFlags.NonPublic | BindingFlags.Static);
                    del = Delegate.CreateDelegate(deltype, mi);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString()); return null;
                }
                object[] callbackargs = new object[args.Length - 2];
    
                if (del.GetType() == typeof(TwoInt32s))
                {
                    for (int i = 2; i < args.Length; i++)
                    {
                        callbackargs[i - 2] = Int32.Parse(args[i]);
                    }
                }
                else if (del.GetType() == typeof(OneString))
                {
                    Array.Copy(args, 2, callbackargs, 0, callbackargs.Length);
                }
    
                var result = del.DynamicInvoke(callbackargs);
    
                return result;
            }
    

     这是整个解决方案的关键所在,主要是构建一个Delegate对象然后调用DynamicInvoke方法,调用DynamicInvoke时,它会保证在内部传递的参数与回调方法期望的参数一致,否则抛出异常,

     执行完成后返回回调方法的返回值,当然了这只是一个测试的示例,还有很多需要修改和完善的地方。

    后台完整代码:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Reflection;
    using System.Web;
    using System.Web.Mvc;
    
    internal delegate object TwoInt32s(Int32 n1, Int32 n2);
    internal delegate object OneString(string str);
    
    namespace MvcApplication1.Controllers
    {
    
        public class HomeController : Controller
        {
            public object DynamicEnvoke(string item1)
            {
                var args = item1.Split('|');
    
                Type deltype = Type.GetType(args[1]);
                if (deltype == null)
                {
                    Console.WriteLine("invalid deltype args");
                    return null;
                }
                Delegate del = null;
                try
                {
                    var mi = typeof(HomeController).GetMethod(args[0], BindingFlags.NonPublic | BindingFlags.Static);
                    del = Delegate.CreateDelegate(deltype, mi);
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.ToString()); return null;
                }
                object[] callbackargs = new object[args.Length - 2];
    
                if (del.GetType() == typeof(TwoInt32s))
                {
                    for (int i = 2; i < args.Length; i++)
                    {
                        callbackargs[i - 2] = Int32.Parse(args[i]);
                    }
                }
                else if (del.GetType() == typeof(OneString))
                {
                    Array.Copy(args, 2, callbackargs, 0, callbackargs.Length);
                }
    
                var result = del.DynamicInvoke(callbackargs);
    
                return result;
            }
    
            public ViewResult Home()
            {
                return View();
            }
    
            private static object Add(int n1, int n2)
            {
                return n1 + n2;
            }
            private static object SubTract(Int32 n1, Int32 n2)
            {
                return n1 - n2;
            }
    
            private static object NumChars(string str)
            {
                return str.Length;
            }
    
            private static object Reverse(string str)
            {
                Char[] chars = str.ToCharArray();
    
                Array.Reverse(chars);
    
                return new String(chars);
            }
        }
    }
    

     前端完成代码:

    @{
        ViewBag.Title = "Home";
    }
    
    <script src="~/Content/jquery-1.9.1.min.js"></script>
    <script type="text/javascript">
        $.get("/Home/DynamicEnvoke", { item1: "NumChars|OneString|4362846327846328" }, function (data) {
            alert(data);
        });
        $.get("/Home/DynamicEnvoke", { item1: "SubTract|TwoInt32s|2|1" }, function (data) {
            alert(data);
        });
    </script>

    下面送上一首情诗:《花痴》

  • 相关阅读:
    AWS re:Invent 2019 召开 | 云原生生态周报 Vol. 30
    更强、更稳、更高效:解读 etcd 技术升级的三驾马车
    Service Mesh 是新瓶装旧酒吗?
    从零开始入门 K8s | 深入剖析 Linux 容器
    阿里云上万个 Kubernetes 集群大规模管理实践
    CNCF 官方大使张磊:什么是云原生?
    函数计算自动化运维实战 3 -- 事件触发自动创建快照
    函数计算自动化运维实战 2 -- 事件触发 eip 自动转移
    函数计算自动化运维实战1 -- 定时任务
    273. Integer to English Words
  • 原文地址:https://www.cnblogs.com/LittleFeiHu/p/4232065.html
Copyright © 2020-2023  润新知