那么“反射”的作用到底是什么?

百合杰 2018-11-15 02:13:10
网上看到一段关于反射的使用代码
            Type t = typeof(TestClass);
Type[] pt = new Type[2];
pt[0] = typeof(string);
pt[1] = typeof(string);
//根据参数类型获取构造函数
ConstructorInfo ci = t.GetConstructor(pt);
//构造Object数组,作为构造函数的输入参数
object[] obj = new object[2] { "grayworm", "hi.baidu.com/grayworm" };
//调用构造函数生成对象
object TestClassA = ci.Invoke(obj);

这代码不就是实例了TestClass吗?为何不直接是
TestClass TestClassB = new TestClass("grayworm", "hi.baidu.com/grayworm");

求解?
...全文
247 22 打赏 收藏 转发到动态 举报
写回复
用AI写文章
22 条回复
切换为时间正序
请发表友善的回复…
发表回复
  • 打赏
  • 举报
回复
反射可以用于扩展系统功能,比如,我们做了某个行业的一套标准版本的企业管理系统,我们这套系统可以卖给很多很多家客户,但不保证每个客户不提出一些个性化的需化。为了快速实现客户需求,你可以让系统具备扩展自定义功能,即可以让用户的个性化需化单独建项目,编译成dll文件,丢系统来执行,这样可以不用修原来系统,减少很多的麻烦。 当然,我们对于反射的dll要实现诸多的限制,比如,必须继承我们定义的标准接口,让系统在调用接口前,就明白dll的结构。
  • 打赏
  • 举报
回复
我们在设计中经常抛出事件来通知宿主去做一些事情(并且带回调用结果),或者是底层一点来维护外部传来的委托,或者是反射一个拥有某个接口的对象,或者反射一个什么接口也不懂的对象.......有许多种设计模式,实际上有几十种上百种流行的编程模式。你可以说反射是最底层的一种概念。如果完全不理解反射,那么可能你其实什么样的灵活代码都不能理解。但是反过来,另有很多人是理解了灵活的需求,却滥用了反射。
  • 打赏
  • 举报
回复
任何事情在底层都肯定会有任做 --> 任何事情在底层都肯定会有人做 就是说,处在哪一层那么你就专注于那一层所必要注重的原则,不可以总是拿底层的技术需求来替代高层次的(领域)业务和(工程)管理经验。例如我们也许需要“查表”来判断程序该调用哪一个方法,那么从最初思路编译为不查表直接调用方法一直到编译为查表之后运用多态技术来使用靠谱的预定义接口来操作,甚至一直到最不靠谱地完全动态操作,有不同的层次。反射就是这一堆工程概念的一块最底层的垫脚石,最低级的必须掌握的一个小伎俩。 那么在不同设计层次要实现不同的设计,建筑工程师在讨论设计时会尽量缩小工地小工的术语的范围(但是肯定不会否定建筑工地的搬砖的小工)。或者换一个说法,比如说你给用户编写一个会计账程序,当程序突然出现问题时,你需要应急地灵活处理,这个时候你最大的本事就是拿着计算器、一天一夜不睡也要给人家用手工方式先计算出一个报表、然后打印成你的程序的A4纸上的报表格式。有些人学习知识,没有学过最底层的知识,那么一旦学过一点这类知识反而觉得特别高大上、特别“万能”,好像什么都能做。忘记了自己所处的岗位,忘记了需要设计一个靠谱的框架、高效率的可继承框架、在编译时能严格地反映bug的框架,就好像是认为手拎锤子可以敲打出各种高档汽车这才是伟大的工匠,就好像是认为把任何一支狗放到大英博物馆的一台打字机面前足够长年份之后它都能打出所有的英文资料。实际上,使用反射必须克制,你只有在开发一些严格和高效率的工具时才在关键的3、4行代码上用点反射,而不是在普通应用中去滥用反射。
  • 打赏
  • 举报
回复
比如说我们强调建筑师要用建筑师的思路来搞设计,而不是用工地上搬砖的小工的思路来“空想”设计。比如说你经常看到初学者——自认为与别人不一样的小孩子——刚捡到一把锤子就喜欢见到任何钉子都砸一砸。对于比较底层的一些概念,有些人喜欢夸大。 不错,任何事情在底层都肯定会有任做。有的时候是编译器已经靠谱地做好了的,有的时候(千分之一的代码中)就需要我们写上几行反射代码。关键就在于工程实践的理解,而不是仅仅知道概念。那么回答“反射的作用是什么”这个问题,其实最需要学会也理解起来有点难度的知识是“反射的弊端是什么”,只有这样才没白学这么高大上的概念。
threenewbee 2018-11-16
  • 打赏
  • 举报
回复
简单来说做两件事,运行时类型识别(RTTI)和动态创建(DC) 比如GetFields、GetProperties、GetMethods... 这些就是RTTI CreateInstance、LoadFrom 这些,就是DC
维秀斯丢丢 2018-11-16
  • 打赏
  • 举报
回复
做插件的时候,拷贝dll文件,即可用反射动态加载程序集,通过接口的方式调用。 这个时候你是不知道具体的实现类型的。
token不能为空 2018-11-16
  • 打赏
  • 举报
回复
引用 9 楼 caozhy 的回复:
简单来说做两件事,运行时类型识别(RTTI)和动态创建(DC) 比如GetFields、GetProperties、GetMethods... 这些就是RTTI CreateInstance、LoadFrom 这些,就是DC
学习了
mk_lucifer 2018-11-16
  • 打赏
  • 举报
回复
用处大的你无法想象,C#常见的配置文件,对象串行化,属性绑定等机制都是依赖于反射。。。做个最简单的描述,一个配置文件,里面明确写着,我要实例一辆车,而不是一匹马,更不是一栋房子。。那么导入器要怎么做? 根据配置文件有一句文本写的是<Car color="black"/>,那么导入器的做法就是根据 xml文件开头描述的命名空间,发现car的C#命名空间是 Objects.Auto 那么他就可以得到他的全名是 Objects.Auto.Car,然后根据类型名称找到类型 Type ,然后通过Type反射出的构造函数构造一个 Car实例,然后通过反射找到 color属性,赋值成黑色。。。这就是反射的用途,如果你深入了解下反射和一些C#的深层机制,就会发现反射几乎无处不在。。。
stevenjin 2018-11-16
  • 打赏
  • 举报
回复
反射DLL人家类库里的东西,还能搞个窗体出来哦
Chrisfrog 2018-11-16
  • 打赏
  • 举报
回复
其实用没用反射的区别就等同于 你看到有个人从正面走过来抱你,和有人从背后抱你然后让你猜猜他是谁
江湖评谈 2018-11-16
  • 打赏
  • 举报
回复
反射 最常用的一个应用, 获取类上面的特性 ModerBinder就是通过这个来绑定模型。 通过路由约定,配置的控制器,因为无法预知控制器的名称,所以也需要用到反射 控制器里面的方法,因为无法预知有几个方法,需要调用哪个方法,所以也要用到反射。 通过CSHTML构建的Razor视图,因为里面的强类型,ViewBag,ViewData也无法预知,所以需要反射CreatInstance创建的类。 总而言之,在 .Net 里面,无法预知的类的符号,需要用到反射。以便确定你最终需要的结果。
xuzuning 2018-11-16
  • 打赏
  • 举报
回复
“反射”的作用到底是什么?
反射使用来探测未知对象特征的一种预置的技术手段
在任何情况下都不是必需的,只不过 Java 有,所以 C# 也才有
只是在一个类包打天下的 Java 理念中,反射有着确定性地位。而在沿袭传统的 C# 中并没有显著的意义
先不说运行效率,大量的使用反射,将模糊掉系统预定的严密流程,导致不确定性增加
但事物总是存在两面性的,这也恰恰是智能化的表现之一

反射作为一个技术手段,应该也必须掌握,但不要在普通应用中使用
  • 打赏
  • 举报
回复
我们可以使用 dynamic 机制来优化书写、提高性能,而不用写反射代码。这里要强调的其实是“少写反射代码”(注意并不是不写反射代码)。
风吹腚腚凉 2018-11-16
  • 打赏
  • 举报
回复
引用 1 楼 sp1234 的回复:
t 通常是作为一个传入的参数。也就是说,你的代码中第一行(先决条件)只是为了 demo 而写的代码,后边的代码才是真正要干的事情。 在编程设计中,要尽可能地少用、不用反射。因为凡是不但会使得程序运行效率慢几百倍,而且更主要地是,其实这类抽象处理的代码的形式验证方面是“不靠谱”的,通常只有在运行时、在运行了几百次当某个特定数据过来时整个程序才会在用户面前丢人地崩溃,而在编译时器是检查不出来设计错误的。 所以编程设计要强类型化。只有千分之一、万分之一的代码才反射。不要滥用反射。
你可以用快速反射库来适当的优化反射的性能
  • 打赏
  • 举报
回复
在正常而靠谱的设计中,你会把 TestClass 设计为 interface 或者 class(包括 abstract class)来实现其可扩展性。例如设计
public interface MyABC
{
    void SetParam(string domain, string url);
}
接口,那么任何实现了这个接口的对象都能被你的代码用来设置你要设置的那两个字符串值了。 只有极端情况需要反射,这时候反射技术就有用了(因为反射毕竟是最底层的技术)。例如
    public interface MyABC
    {
        void SetParam(string domain, string url);
    }

    void t()
    {
        string asmName = "Test";
        string typeName = "TestClass";
        var asm = Assembly.Load(asmName);
        var type = asm.GetType(typeName);
        var obj = (MyABC)Activator.CreateInstance(type);
        obj.SetParam("grayworm", "hi.baidu.com/grayworm");
        .......
    }
这类代码,虽然 type 是动态的,但是之后就以强类型的(多态的)方式来使用,这就平衡了运行性能、开发性能、保证调试维护的特性了。不需要反射的地方不滥用反射,而需要反射的地方(例如从配置文件中读取 asmName、typeName 进行动态操作)则精准地使用反射。
正怒月神 2018-11-15
  • 打赏
  • 举报
回复
就光你贴出的反射代码来看,其实没什么意义。
大然然 2018-11-15
  • 打赏
  • 举报
回复
通过字符串调用方法
  • 打赏
  • 举报
回复
反射就是一切都从原始社会、从最顶层去动态重建一切过程 --> 反射就是一切都从原始社会、从最初级去动态重建一切过程
  • 打赏
  • 举报
回复
举个“中间概念”的例子,比如说程序中有个经常需要扩展的功能要反射,因为你觉得 t 这个参数只可能是变动并且是顶层的 Type,不可能是一个靠谱的预先知道具体名字的 interface 或者 class(预先知道名字,那么你就可以用强类型化、多态的方式来设计程序,而不用反射)。 这个时候,反射仍然是比“委托”低效很多倍的。如果你把
ci.Invoke(obj)
这类代码生成为一个确定强类型的 Delegate,然后把这个 Delegate 针对不同的 obj 而反复调用,都比反射代码来的效率搞。因为反射中你的代码假设 obj 的信息什么都不知道、从头开始读取对象信息,而这个过程其实只要做第一遍、然后就动态生成 Delegate 作为缓存而反复调用,就能节省反复进行反射操作的时间了。 总之,反射就是一切都从原始社会、从最顶层去动态重建一切过程。有的人以为这样就高大上、就”万能“,但是有经验的人知道当我们只关心”正确性“而不关心运行效率和开发设计效率时,才会自欺欺人地以为越是低级的代码越高大上。
  • 打赏
  • 举报
回复
同样的意思,有些人喜欢滥用什么“注入、反转”概念,觉得高大上。实际上程序可能被注入工具改得面目全非无法正常调试理解了,而且胡乱插入的抽象也会干扰调试者的理解思路甚至超出一般人的调试的脑容量。真正的这类程序应该明确地在接口中强类型地去设计事件,只有这样才能靠谱地设计和调试程序,而不是滥用什么抽象注入反转工具。 作为抽象功能,我们必定早晚都需要使用。但是要知道用到关键点上,而且不能滥用。真正会用到抽象、依赖反转、扩展、工厂、反射功能的人,反而不会滥用反射。
加载更多回复(2)

110,524

社区成员

发帖
与我相关
我的任务
社区描述
.NET技术 C#
社区管理员
  • C#
  • Web++
  • by_封爱
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

让您成为最强悍的C#开发者

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