C#高级编程之反射

反射的定义

MSDN定义:反射提供描述程序集、模块和类型的对象(Type类型)。 可以使用反射动态地创建类型的实例,将类型绑定到现有对象,或从现有对象中获取类型,然后调用其方法或访问器字段和属性。 如果代码中使用了特性,可以利用反射来访问它们。

一共三句话。

第一句意思是可以利用反射提供的API来获取程序集信息,包括其下的模块、Type类型信息;

第二句意思通过反射,先拿到这个程序集->Module->Type的类型信息,然后调用实例化的API Activator.CreateInstance(type type)来实例化该类型对象,拿到对象instance后,可以对这个对象数据成员进行赋值,然后注入到现有对象B中;或者是利用API获取这个类型下的属性、方法等信息,对其进行读写、调用操作。

第三句意思是:如果反射获取到的这个类型有使用Attribute特性,可以进行互操作。

反射使用

反射一般使用过程如下:

装载程序集Assmebly

上面的方法讲的是反射AppDomain的所有程序集,我们可以显示的调用其中的一个程序集,system.reflecton.assembly 类型提供了下面三种方法:
1、Load 方法:极力推荐的一种方法,Load 方法带有一个程序集标志并载入它,Load 将引起CLR把策略应用到程序集上,先后在全局程序集缓冲区,应用程序基目录和私有路径下面查找该程序集,如果找不到该程序集系统抛出异常
2、LoadFrom 方法:传递一个程序集文件的路径名(包括扩展名),CLR会载入您指定的这个程序集,传递的这个参数不能包含任何关于版本号的信息,区域性,和公钥信息,如果在指定路径找不到程序集抛出异常。
3、LoadWithPartialName:永远不要使用这个方法,因为应用程序不能确定再在载入的程序集的版本。该方法的唯一用途是帮助那些在.Net框架的测试环节使用.net 框架提供的某种行为的客户,这个方法将最终被抛弃不用。

注意:system.AppDomain 也提供了一种Load 方法,他和Assembly的静态Load 方法不一样,AppDomain的load 方法是一种实例方法,返回的是一个对程序集的引用,Assembly的静态Load 方发将程序集按值封装发回给发出调用的AppDomain.尽量避免使用AppDomain的load 方法。

获取类型信息

    //定义一个获取反射内容的方法
        static void getreflectioninfo(Assembly myassembly)
        {
            Type[] typearr = myassembly.GetTypes();//获取类型
            foreach (Type type in typearr)//针对每个类型获取详细信息
            {
                //获取类型的结构信息
                ConstructorInfo[] myconstructors = type.GetConstructors();

                //获取类型的字段信息
                FieldInfo[] myfields = type.GetFields();

                //获取方法信息
                MethodInfo[] myMethodInfo = type.GetMethods();

                //获取属性信息
                PropertyInfo[] myproperties = type.GetProperties();

                //获取事件信息
                EventInfo[] Myevents = type.GetEvents();
            }
        }

调用普通类泛型方法

泛型方法签名:public void Show<T,W,X>(T t,W,w,X x);

Assembly assmebly=Assembly.Load("")
Type type=assembly.GetType("namespace.sqlServerHelper");
dbHeperInstace =Activator.CreateInstace(type)
MethodInfo genericMethod=type.GetMethod("show");
MethodInfo genericMethod1=genericMethod.MakeGenericMethod(new Type[]{typeof(int),typeof(string),typeof(DateTime)};
genericMethod1.invoke(dbHeperInstace,new object[]{123,"john",DateTime.Now};

调用泛型类里面泛型方法

【[此处的Show方法的具体参数的type类型依赖于class上的<T,W,X>]】eg.

class GenericClass<T,W,X>
{
public void Show<T,W,X>(T t,W,w,X x)
}
[占位符]
Type type=assembly.GetType("namespace.sqlServerHelper.GenericClass`3");
Type type1=type.MakeGenericType(new Type[]{typeof(int),typeof(string),typeof(DateTime)};
object GenericdbHeperInstace =Activator.CreateInstace(type1);
MethodInfo genericMethod=type1.GetMethod("show");
genericMethod.invoke(GenericdbHeperInstace,new object[]{123,"john",DateTime.Now});

反射设置属性值

对于属性的操作具体可以参考 https://blog.csdn.net/shuzhongke123/article/details/106091047

总结

反射特点:
动态 减少对象与对象之间的依赖,只需要知道类名,方法名就可以调用,还可以突破特定权限,可以做到普通方式无法做到的。
性能问题:经过缓存优化之后,是普通的10倍。对于性能损耗,请理性看待。

参考:https://www.cnblogs.com/wangshenhe/p/3256657.html

 

posted @ 2020-11-19 21:43  liweiyin  阅读(130)  评论(0编辑  收藏  举报