反射简单入门教程

       大家都知道,我们用VS编写的代码经过编译后会生成程序集(一般是dll文件或者exe运行程序),当我们需要在别的应用程序中要使用该程序集时直接通过添加引用的方式就可以了,而且在VS中,可以直接通过对象流浪器的方式来查看该dll程序集的信息!对于这种“静态”引用程序集是完全没问题,现在假如我们想在某个应用程序中动态的添加某些程序集时,通过这种添加引用的方式显然是不行的了!还有一种情况,假如我们想查看某个程序集下所有的类型、方法,并进行输出时,显然按照我们刚才所说的在VS中通过对象浏览器查看这种方式显然也不在适用了!那么,我们有什么好的办法来解决这些问题呢!答案当然就是反射啦……哈哈!反射(Reflection)是.NET中的重要机制,通过放射,我们可以在程序运行时动态的加载某个程序集,然后可以实例化该程序集下某些类并调用想要调用的方法;通过反射我们循环获取该程序集下的所有类型(包括类、方法、属性、成员等)信息,然后输出查看,可以说是很方便!好了,说了这么多,我们来些code看看吧!

       示例1:首先,第一个例子我们通过反射来查看.NET框架中一个非常重要的程序集的信息(mscorlib.dll,mscorlib.dll是.NET框架非常核心的组件,只要你运行时.NET框架类库,这个类库就一定会加载),在这里我们是通过循环方式输出该程序集下的所有的类型信息:

       引用命名空间:using System.Reflection; 

namespace Web
{
    public partial class TestOne : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 调用dll输出相关信息
        /// </summary>
        protected void btnPrint_Click(object sender, EventArgs e)
        {
            //注意程序集的load方法,它接受的参数是一个程序集的名称,而不是一个路径,也就是说,
            //所要加载的dll必须和当前应用程序同时加载进来,而且必须在当前目录下
            System.Reflection.Assembly assembly = System.Reflection.Assembly.Load("mscorlib.dll");

            StringBuilder strOut = new StringBuilder();
            strOut.Append(String.Format("程序集的名称:{0}<br/>", assembly.FullName));
            strOut.Append(String.Format("程序集的类型:{0}<br/>", assembly.GetType()));

            //获取程序集下总共定义的类型的一个数组,即该程序集下一共定义了多少个类,返回所有类的一个数组
            Type[] T = assembly.GetTypes();
            foreach (Type item in T)
            {
                strOut.Append(String.Format("{0}<br/>", item.FullName));
            }
            Response.Write(strOut.ToString());
        }
    }
}

       示例2:第二个例子我们动态加载一个程序集,然后通过反射来实例化一个该程序集下的一个类,并调用该类下一个方法获取返回值:我们建立一个空的解决方案,命名ReflectionTest,然后在该解决方案下面添加一个ASP.NET Web应用程序和一个类库应用该程序,如下图:

       在类库ClassLibraryOne里面只有一个类UsersClass.cs,我们贴上UsersClass.cs的代码:

namespace ClassLibraryOne
{
    public class UsersClass
    {
        private String userName;
        public String UserName
        {
            get { return userName; }
            set { this.userName = value; }
        }

        /// <summary>
        /// 无参构造函数
        /// </summary>
        public UsersClass()
        {
            this.userName = "这里是userName的值,恭喜获取成功!(无参数构造函数)";
        }

        /// <summary>
        /// 有参构造函数
        /// </summary>
        public UsersClass(String username)
        {
            this.userName = username;
        }

        //下面定义了三个返回username的方法,分别用于测试,看后面通过反射能调用哪个方法
        public String PrintNameByPublic()
        {
            return this.UserName;
        }

        private String PrintNameByPrivate()
        {
            return this.UserName;
        }

        protected String PrintNameByProtected()
        {
            return this.UserName;
        }
    }
}

       然后在Web层添加一个页面,在页面后天添加System.Reflection命名空间,代码如下:  

using System.Reflection;

namespace Web
{
    public partial class TestTwo : System.Web.UI.Page
    {
        protected void Page_Load(object sender, EventArgs e)
        {

        }

        /// <summary>
        /// 动态调用解决方案中的类库的dll,并实例化其中的类和调用该类下的方法
        /// 注意:因为是动态添加,所以应用程序本身不能再对类库添加引用
        /// </summary>
        protected void btnPrint_Click(object sender, EventArgs e)
        {
            //调用assembly的LoadFrom方法,就可以加载任何位置上面的dll,它不同于load方法
            String dllPath = @"F:/资料/a其他写的一些例子/反射/ReflectionTest/ClassLibraryOne/bin/Debug/ClassLibraryOne.dll";
            System.Reflection.Assembly assembly = System.Reflection.Assembly.LoadFrom(dllPath);

            //获取程序集的类型(当然先要循环输出才知道),在这里我们假设已经先通过遍历输出知道里面的类型了
            Type NewObj = assembly.GetType("ClassLibraryOne.UsersClass");

            //创建动态加载程序集中的一个实例,这里我们创建了一个UsersClass类的一个实例
            Object myObj = Activator.CreateInstance(NewObj);

            //这里我们通过GetMethods方法返回该程序集下所有的方法,还有GetFields(获取所有字段),GetMembers(获取所有成员)等
            //通过它里面提供的方法我们就可以看到类下所有的内容了
            MethodInfo[] MIS = NewObj.GetMethods();

            //可以通过一个方法名获取动态程序集的方法
            MethodInfo MI_public = NewObj.GetMethod("PrintNameByPublic");             //获取公共方法,成功的

            MethodInfo MI_private = NewObj.GetMethod("PrintNameByPrivate");          //获取私有方法,是失败的,不能获取私有方法

            MethodInfo MI_protected = NewObj.GetMethod("PrintNameByProtected");   //获取受保护方法,也是失败的,不能搞获取私有方法

            //调用方法,得到返回值Invoke方法的第二个参数就是对应要调用方法所接受参数,在这里没有参数,所以就用null
            String strOut = MI_public.Invoke(myObj, null).ToString();
            Response.Write(strOut);
        }
    }

       在这里,还有一点要提醒一下,可能由于我们在平时做项目时习惯的原因,喜欢通过添加引用的方式在刚才的Web层添加我们刚在解决方案中新建的类库,但是,在这里我们就不要在添加引用了哦!因为我们是通过动态加载进来的,如果你再添加引用那我们在这里做的不就失去意义了吗?哈哈……

         

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值