MethodInfo Invoke 反射不同方法 怎么样传递不同参数

梅子 2016-07-14 03:09:02

public class RegisterPhoneValidate : IHttpHandler, IRequiresSessionState
{
JavaScriptSerializer JS = new JavaScriptSerializer();
string function = string.Empty;
public void ProcessRequest(HttpContext context)
{
context.Response.ContentType = "text/plain";
function = context.Request["f"];
MethodInfo method = typeof(RegisterPhoneValidate).GetMethod(function);
if (method != null)
{
switch (function)
{
case "AA":
method.Invoke(this, new object[] { context.Request["phone"] });
break;
case "BB":
method.Invoke(this, new object[] { context.Request["phoneCode"], context.Request["verifyCode"], context.Request["phone"] });
break;
default:
break;
}
}
}

public bool IsReusable
{
get
{
return false;
}
}

public void AA(string Phone)
{
...
}

public void BB(string PhoneCode,string VerifyCode,string Phone)
{
...
}



我上面这种方法虽然也能实现,但是感觉有点怪,有没有大大能指点我一下,这个反射怎样辨认不通方法,传递不通的参数
...全文
400 13 打赏 收藏 转发到动态 举报
写回复
用AI写文章
13 条回复
切换为时间正序
请发表友善的回复…
发表回复
梅子 2016-07-15
  • 打赏
  • 举报
回复
谢谢大大们指点,获益匪浅
  • 打赏
  • 举报
回复
假设你的 ashx 端这样获得两个参数
public void ProcessRequest (HttpContext context) {
    var f = context.Request.QueryString["f"];
    var data = new StreamReader(context.Request.InputStream).ReadToEnd();
    .............................
}
客户端通常可以这样写,比如对于 javascript 端,可以是
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script type="text/javascript">
    var obj = {
        abc: 1213,
        def: [
            {
                u1: "q3412",
                u2: 9239
            },
            {
                u1: "阿什顿",
                u2: 9827
            }
        ],
        ghi: true
    };
    $.ajax({
        url: ".........ashx?f=haha",
        data: JSON.stringify(obj),
        type: "post",
        succ: ......
    });
</script>
而 .net 客户端则可以写
var obj = ......
JavaScriptSerializer serializer = new JavaScriptSerializer();
var res = new WebClient().UploadData("http://......:...../......ashx?f=cmd423", Encoding.UTF8.GetBytes(serializer.Serialize(obj)));
这样的形式,其实可以 post 比较传送复杂的对象,并且显然不需要跟服务器端的字段、属性定义完全匹配,也能传送。 你可以看到,不论是 javascript 端的 obj,还是 c# 客户端的 obj,都是自然的前端对象,可以嵌入复杂的结构,只要跟 Command 的复杂属性定义匹配就行了。 而你是看成了一堆的 string 参数。这就比较麻烦。
  • 打赏
  • 举报
回复
表面上看,这是把你的
        public void AA(string Phone)
        {
            ...
        }
 
        public void BB(string PhoneCode,string VerifyCode,string Phone)
        {
           ...
        }
变为对象(类)、接口,似乎抽象了一些,麻烦了一些。 但是如果你专门设计架构时就知道了。客户端的每一个请求其实要重视它,要把它作为一个对象,进行一系列企业式的工作流处理,将来不断扩展这个后端工作流。
  • 打赏
  • 举报
回复
我再给你扩展一点,假设再解析程序这一端,发现将来的“高级命令”需要默认增加一些更加复杂的属性值,但是同时又保证跟原始命令解析相兼容,那么可以简单地给 ICommand 接口扩展一个 ICommandV2 版本出来。例如
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        static Dictionary<string, Type> db = new Dictionary<string, Type>();

        static void Main(string[] args)
        {
            db.Add("命令1", typeof(Command1));
            db.Add("命令2", typeof(Command100));
            db.Add("XX", typeof(Command200));
            Console.WriteLine(解析并执行命令("命令1", "{code: \"abcd\", times:1}"));
            Console.WriteLine(解析并执行命令("命令2", "{codes: [\"abcd\", \"中国人民银行\"], times:1}"));
            Console.WriteLine(解析并执行命令("XX", "{times:1234}"));
            Console.WriteLine("..............press ant key");
            Console.ReadKey();
        }

        private static object 解析并执行命令(string f, string data)
        {
            Type t;
            if (!db.TryGetValue(f, out t))
                throw new Exception(string.Format("没有命令对象能处理【{0}】请求。", f));

            JavaScriptSerializer serializer = new JavaScriptSerializer();   //注意要引用 System.WebExtension 程序集
            var cmd = (ICommand)serializer.Deserialize(data, t);
            if (cmd is ICommandV2)
                ((ICommandV2)cmd).执行时间 = DateTime.Now;
            return cmd.Execute();
        }
    }

    public interface ICommand
    {
        object Execute();
    }

    public class Command1 : ICommand
    {
        public string code;
        public int times;

        public object Execute()
        {
            return "我执行了1   " + code + "     " + times;
        }
    }

    public class Command100 : ICommandV2
    {
        public string[] codes;
        public long times;

        public DateTime 执行时间 { get; set; }

        public object Execute()
        {
            return this.执行时间 + "     我执行了2   " + string.Join(",", codes) + "     " + times;
        }
    }

    public class Command200 : ICommand
    {
        public long times;

        public object Execute()
        {
            return times + times;
        }
    }

    public interface ICommandV2 : ICommand
    {
        DateTime 执行时间 { get; set; }
    }

}
你从这里可以看到,基本上不写什么反射代码。反射只在1万行代码中写2、3就够了。即使命令解析机制后来扩展了,它也是强类型编程!1万行代码中尽量不写反射代码,其它部分一定是基于接口设计,是强类型编程,不是“怪怪的”若类型编程。 我很欣赏你能对弱类型感觉“怪”。这是一个好的开始。
Poopaye 2016-07-14
  • 打赏
  • 举报
回复
引用 3 楼 sunnxxy 的回复:
我就想说有没有其他方法可以识别是哪个方法,然后自动填装参数的。。
我就问你 AA和phone BB和phoneCode、verifyCode、phone 要怎么自动联系到一起??
  • 打赏
  • 举报
回复
面向对象、面向接口,你就能找到真正的扩展的基础。 因为当你将“命令”看成是独立的对象(类)之后,所有对象设计技术你都能用起来,你能把一个单独的“请求”看成是活的对象、而不是一个死的字符串。例如,你可以扩展一个 Log 方法来操作 ICommand 兼容对象。你也可以在某些泛型类中使用到 ICommand 作为类型参数。熟悉的.net 中到处都是针对着各种对象来设计的公共程序框架。 如果你面向方法,除了一点点”动态解析“的弱类型语句,能有多大发展呢?熟悉的.net 代码框架中,你用得上哪些呢? 所这里如果你能把命令真正看作对象,那就跟看不到对象、面向对象设计,完全不是一个层面的了。
  • 打赏
  • 举报
回复
至于说你的 QueryString 如何组装为 json 那样的 { phone: "......"} 或者 { phoneCode:...., phone:..... } 的形式,那是你自己的事情。你甚至可以考虑一下使用 post 而不是 get 方式传参,能承载更大的 data。 我前些天在 csdn 回复了一个“插件热修补”的例子,使用了 MEF。通过它,你的程序就可以以无限扩展地、动态地自动通过 MEF 来加载各种各样不同的 ICommand,而不需要像这里这样写死 3 个 db.Add代码。而且 MEF 可以到其它应用程序目录下去查找 dll、.exe,在你的程序运行时去加载插件。并且解决了许多你自己反射代码可能产生的问题。 但是前提是,先把我这里的例子搞明白。那样你才能比较方便地去领会 MEF 之类的框架的比这个更神奇得多的机制。
  • 打赏
  • 举报
回复
我给你写一个简单的例子:
using System;
using System.Collections.Generic;
using System.Web.Script.Serialization;

namespace ConsoleApplication1
{
    class Program
    {
        static Dictionary<string, Type> db = new Dictionary<string, Type>();

        static void Main(string[] args)
        {
            db.Add("命令1", typeof(Command1));
            db.Add("命令2", typeof(Command100));
            db.Add("XX", typeof(Command200));
            Console.WriteLine(解析并执行命令("命令1", "{code: \"abcd\", times:1}"));
            Console.WriteLine(解析并执行命令("命令2", "{codes: [\"abcd\", \"中国人民银行\"], times:1}"));
            Console.WriteLine(解析并执行命令("XX", "{times:1234}"));
            Console.WriteLine("..............press ant key");
            Console.ReadKey();
        }

        private static object 解析并执行命令(string f, string data)
        {
            Type t;
            if (!db.TryGetValue(f, out t))
                throw new Exception(string.Format("没有命令对象能处理【{0}】请求。", f));

            JavaScriptSerializer serializer = new JavaScriptSerializer();   //注意要引用 System.WebExtension 程序集
            var cmd = (ICommand)serializer.Deserialize(data, t);
            return cmd.Execute();
        }
    }

    public interface ICommand
    {
        object Execute();
    }


    public class Command1 : ICommand
    {
        public string code;
        public int times;

        public object Execute()
        {
            return "我执行了1   " + code + "     " + times;
        }
    }

    public class Command100 : ICommand
    {
        public string[] codes;
        public long times;

        public object Execute()
        {
            return "我执行了2   " + string.Join(",", codes) + "     " + times;
        }
    }

    public class Command200 : ICommand
    {
        public long times;

        public object Execute()
        {
            return times + times;
        }
    }
}
这里,首先用 db 来记录了n个命令,准备用来处理客户端请求。 而命令其实可以看成两部分,一部分用来识别命令类型,另一部分就是命令参数。 每一个命令的接口其实都是 ICommand。因此你从最核心的那个“解析”方法中就看到了,它纯粹是依赖接口来设计开发的!
tcmakebest 2016-07-14
  • 打赏
  • 举报
回复
感觉怪怪的? 用反射本身就很怪, 请适应吧
bidisty 2016-07-14
  • 打赏
  • 举报
回复
这地方有 必要用到反射吗?直接调用方法就好了。
梅子 2016-07-14
  • 打赏
  • 举报
回复
我就想说有没有其他方法可以识别是哪个方法,然后自动填装参数的。。
Poopaye 2016-07-14
  • 打赏
  • 举报
回复
要么所有方法都以HttpRequest为参数
        public void AA(HttpRequest request)
        {
            string Phone = request["phone"];
            ...
        }
 
        public void BB(HttpRequest request)
        {
           ...
        }
Poopaye 2016-07-14
  • 打赏
  • 举报
回复
那你想怎样?

62,041

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术交流专区
javascript云原生 企业社区
社区管理员
  • ASP.NET
  • .Net开发者社区
  • R小R
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

.NET 社区是一个围绕开源 .NET 的开放、热情、创新、包容的技术社区。社区致力于为广大 .NET 爱好者提供一个良好的知识共享、协同互助的 .NET 技术交流环境。我们尊重不同意见,支持健康理性的辩论和互动,反对歧视和攻击。

希望和大家一起共同营造一个活跃、友好的社区氛围。

试试用AI创作助手写篇文章吧