Unified client call portal with delegation and reflection
Reflection: reflection is a powerful mechanism that allows you to discover and use types and their members that you do not know at runtime;
Delegate: System. Delegate provides several methods. When you do not know the required information of the Delegate during compilation, you can use several methods provided to create and call a Delegate, CreateDelegate and DynamicInvoke.
When creating MVC or WebAPI projects, we often encounter dynamic interaction between JS and the background. According to the previous logic, each request corresponds to a different URL (that is, different background actions ), over time, it is very difficult to maintain the situation,
$.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); });
Each page has several interactions, and different pages have many different interactions. Each module .......
However, with the reflection and delegation mechanisms provided by the great. net platform, we can finally change this chaotic situation and unify the portal for front-end and back-end data interaction:
Here is a test case:
Front-end Ajax request:
<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>
Since it is a unified entry, we can see that the URL does not change, but only the input parameters are changed. Each parameter is separated by |. The client URL can be encapsulated into constants or other methods.
What is DynamicEnvoke? The Public method at the backend entry only transmits a string type parameter. Here, you can rewrite the Model binding mechanism to support more advanced Model types (such as arrays, sets, and dictionaries, complex types. For details, refer
Simulate the Model binding mechanism of ASP. net mvc through an instance: array series of articles ):
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; }
This is the key to the entire solution. It mainly constructs a Delegate object and then calls the DynamicInvoke method. When DynamicInvoke is called, it will ensure that the parameters passed internally are consistent with the expected parameters of the callback method, otherwise, an exception is thrown,
After the execution is complete, the return value of the callback method is returned. Of course, this is just a test example, and there are many points that need to be modified and improved.
Complete background code:
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); } }}
Front-end completion code:
@{ 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>
The following is a love poem: "crazy"