文章参考来源:https://www.cnblogs.com/wangshenhe/p/3256657.html
https://www.cnblogs.com/Stephenchao/p/4481995.html
感谢:SamWang , Stephen_潮
认知尚浅,如有错误,愿闻其详!
对反射的理解
首先,我们要晓得,.Net应用程序由程序集(Assembly)、模块(Module)、类型(class)组成,反射,则是一种编程方式,动态的去获取装配件(编译出的.dll或.exe文件)信息和创建对象、调用方法。
- 1、通过反射这种方式去了解类或者是程序集内部结构及功能,获得程序集或程序集中的每个类型(包括类、构造函数、委托、接口、方法和属性等),然后利用获取到的信息进行创建对象等操作。
- 2、程序运行时动态创建对象并执行其中的方法。
为什么要用反射?
反射,整个过程大概就是在程序运行状态下,动态的去获取某个程序集的信息,然后利用信息创建对象,调用方法,实现功能。
问题是我们明明是可以在开发时将代码写好,为什么还要动态创建,繁琐且效率受影响?
其实,donNet的类库实现基本是使用反射实现的调用,他的效率及影响取决于你是否能合适的去使用。凡事有两面性,合适应用可提高程序的复用性和 灵活性,否则适得其反。
举个例子:
在一个媒体播放的软件中,我们希望其他人可以编写一些插件来扩充这个软件的功能,这时,我们在开发的时候,就需要在该软件中留下对应的接口,如下。
public interface IMediaFormat
{
string Extension { get; }//拓展名
Decoder GetDecoder();//解码对象
}
上例中的接口包含Extnsion属性,这个属性返回支持解码的拓展名,方法是返回一个解码对象(默认存在Decoder类,该类提供对文件的解码,插件实现接口即可),通过解码对象处理后,我们就可以获得解释的文件流。
然后,我们开发就规定所有的解码插件都必须要派生一个解码器,并且实现这个接口,在GetDecoder方法中返回解码器对象,并且将其类型的名称配置到我们的配置文件里。
最后,我们就不需要在开发播放器时就完整的把所有类型的媒体格式都放进去,只需要从配置文件中获取解码器类型名称,而动态的创建媒体格式对象,将其转换成IMediaFormat接口来使用,即可实现功能。
如何用反射?
反射用到的主要类:
System.Type 类--通过这个类可以访问任何给定数据类型的信息。
System.Reflection.Assembly类--它可以用于访问给定程序集的信息,或者把这个程序集加载到程序中。
(1)使用Assembly定义和加载程序集,加载在程序集清单中列出模块,以及从此程序集中查找类型并创建该类型的实例。
(2)使用Module了解包含模块的程序集以及模块中的类等,还可以获取在模块上定义的所有全局方法或其他特定的非全局方法。
(3)使用ConstructorInfo了解构造函数的名称、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(4)使用MethodInfo了解方法的名称、返回类型、参数、访问修饰符(如pulic 或private)和实现详细信息(如abstract或virtual)等。
(5)使用FiedInfo了解字段的名称、访问修饰符(如public或private)和实现详细信息(如static)等,并获取或设置字段值。
(6)使用EventInfo了解事件的名称、事件处理程序数据类型、自定义属性、声明类型和反射类型等,添加或移除事件处理程序。
(7)使用PropertyInfo了解属性的名称、数据类型、声明类型、反射类型和只读或可写状态等,获取或设置属性值。
(8)使用ParameterInfo了解参数的名称、数据类型、是输入参数还是输出参数,以及参数在方法签名中的位置等。
代码
创造一个具有字段、无参构造函数、有参构造函数、获取字段的方法以及Value属性的程序集
public class TestReflection
{
private string _value;
/// <summary>
/// 无参构造函数
/// </summary>
public TestReflection()
{
}
/// <summary>
/// 有参构造函数
/// </summary>
/// <param name="value">传入参数</param>
public TestReflection(string value)
{
_value = value;
}
/// <summary>
/// 处理方法
/// </summary>
/// <param name="prefix">传入值</param>
/// <returns>处理结果</returns>
public string GetValue(string prefix)
{
if (_value == null)
return "NULL";
else
return prefix + " : " + _value;
}
/// <summary>
/// 属性
/// </summary>
public string Value
{
set
{
_value = value;
}
get
{
if (_value == null)
return "NULL";
else
return _value;
}
}
}
实现对以上这个程序集的反射处理。
//获取类型信息
Type t_1 = Type.GetType("ReflectionDemo.TestReflection");
Console.WriteLine(t_1);
//构造器的参数
object[] constuctParms = new object[] { "构造函数传入参数" };
//根据类型创建对象
object dObj = Activator.CreateInstance(t_1, constuctParms);
//获取方法的信息
MethodInfo method = t_1.GetMethod("GetValue");
//调用方法的一些标志位,这里的含义是Public并且是实例方法,这也是默认的值
BindingFlags flag = BindingFlags.Public | BindingFlags.Instance;
//GetValue方法的参数
object[] parameters = new object[] { "Hello" };
//调用方法,用一个object接收返回值
object returnValue = method.Invoke(dObj, flag, Type.DefaultBinder, parameters, null);
Console.WriteLine(returnValue.ToString());
网友评论