C#之反射学习入门简介

C#之反射学习入门简介

在c#中,通过反射能够更加灵活高效地实现想要的功能,接下来我们就一起来看看反射到底能给我们带来什么好处

首先新建一个接口类库

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace DB.Interface
{
    public  interface IDBHelper  //定义一个接口
    {
        void Query();  //定义一个方法
    }
}

然后生成dll文件
这里写图片描述
接着新建一个DB.Sqlserver类库,并实现上面的接口(在该类库中要引用上面类库生成的dll文件)

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using DB.Interface;
using System.Configuration;
using  System.Data;
using System.Data.SqlClient;
using System.Text;

namespace DB.Sqlserver
{
    public class DBHelper : IDBHelper
    {
        private string connString = ConfigurationManager.AppSettings["YHConnect"];
        private SqlConnection conn;

        public DBHelper()
        {
            Console.WriteLine("连接SqlServer");
            conn = new SqlConnection(connString);
        }
        public void Query()
        {
            Console.WriteLine("这里是{0}的Query", this.GetType().FullName);
            Console.WriteLine("此为无参方法");
        }

        public void Query(string id)
        {
            Console.WriteLine("参数为{0}", id);
        }

        private void test()
        {
            Console.WriteLine("私有方法");
        }
}

然后采用同样的方法生成该类库的dll文件,然后再添加一个控制台程序
这里写图片描述
并为该引用程序添加对接口DB.Interface的dll文件的引用。此时项目的文件结构如图所示。
这里写图片描述

接下来的关键步骤就是要把DB.Sqlserver的dll文件复制到控制台程序的bin目录下
这里写图片描述
这里写图片描述

也就是要把DB.Sqlserver.dll文件从第一幅图的路径复制到第二幅图的路径下。主要是为了在控制台程序中能动态加载到这个dll文件。

然后为控制台程序添加一个配置文件

接下来在控制台程序中添加一下代码来动态加载dll文件

这里写图片描述

然后再配置文件中的configuration节点添加以下代码

<appSettings >
    <add key="SqlHelper" value="DB.Sqlserver.DBHelper,DB.Sqlserver"/>
  </appSettings>

用来配置dll的信息,其中DB.Sqlserver是dll文件的文件名,DB.Sqlserver.DBHelper指向了该dll中具体的某个类,即DB.Sqlserver命名空间下等的DBHelper类。

1 动态加载dl并实例化对象
至此准备工作已经做完,接下来就可以在控制台程序中动态地调用dll文件了。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Reflection;
using System.Configuration;
using Model;
using DB.Sqlserver;


namespace MyReflection
{
    public class Program 
    {

        static void Main(string[] args)
        {
            string spaceName = ConfigurationManager.AppSettings["SqlHelper"];  //可配置
            string[] nameArray = spaceName.Split(',');  //从配置文件获取dll文件信息

            Assembly ammenblyDBHelper = Assembly.Load(nameArray[1]);  //反射的入口 动态加载一个dll文件
            Type dBHelperType = ammenblyDBHelper.GetType(nameArray[0]);//获取盖扩展程序中的某个类
            Object dBHelperObject = Activator.CreateInstance(dBHelperType);  //实例化对象

        }
    }
}

2 访问实例化出来的对象的方法和属性
此时我们就已经获取到了dll文件,并实例化了DBHelper类的对象,但此时这个对象时Object类型的,无法访问DBHe类的具体属性和方法。接下来我们来继续学习如何获取该对象下的方法。

我们课采用Type.GetMethod()来获取指定的某个方法 可参考MSDN文档

//动态加载方法并调用  加载无参方法
// 第一个参数表示方法名称,第二个表示该方法的参数类型
MethodInfo QueryDoMain = dBHelperType.GetMethod("QueryDoMain", new Type[] { });

//调用刚才获取到的方法,并给出参数数组,第一个参数为该方法所属的对象
QueryDoMain.Invoke(dBHelperObject, new Object[] { "123" })

也可采用Type.GetMethods()方法来获取某个对象下的所有方法,该方法返回的是一个MethodInfo[]方法,可用foreach()来遍历。
上述方法只能获取访问属性为public的方法,若要获取访问属性为private的 test()方法,可用以下方法是来获取

//获取私有方法
MethodInfo Test = dBHelperType.GetMethod("test", BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic);
Test.Invoke(dBHelperObject, null);

同样我们可以采用Type.GetProperties()`方法来获取某个Type类型变量下的所有属性,返回的是一个PropertyInfo[]数组,同样可用foreach()来遍历。

PropertyInfo id = typePeople.GetProperty(“id”); // 获取某个Type下的属性
PropertyInfo name = typePeople.GetProperty(“name”);

id.SetValue(oPeople, “123”, null); //设置值
name.SetValue(oPeople, “LC”, null);

3 反射的可配置

反射之所以可配置,就是因为它是通过dll的文件名来动态加载dll文件的(前提是该dll文件要放在指定目录下)。可通过修改配置文件中的相关信息来加载不同的dll文件
再添加一个与DB.Sqlserver类似DB.Mysql类库,同样要添加对DB.Interface.dll的引用,再生成该类库的dll文件,然后将该dll文件复制到控制台程序的Debug文件夹下。

此时若想ammenblyDBHelper加载的是DB.Mysql的dll,只需将App.congfig的

<add key="SqlHelper" value="DB.Sqlserver.DBHelper,DB.Sqlserver"/>
/>

改成

<add key="SqlHelper" value="DB.Mysql.DBHelper,DB.Mysql" />

因为配置文件修改了,所以就会加载不同的dll(应用程序扩展)文件。

4 通过反射和泛型实现数据库表的通用查询功能

首先是数据库的连接配置,在App.congfig添加数据库的连接信息

<add key="YHConnect" value="Data Source=.;Initial Catalog=YH;Integrated Security=True"/>

接下来创建实体层,即Model类库,并添加Employee类

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace Model
{
    //员工实体
    public class Employee
    {
        //员工表的属性
        public string JobNumber { set; get; }
        public string Name { set; get; }
        public string Pwd { set; get; }
        public int EmployeeState { set; get; }
    }
}

然后为该类库生成dll文件,并为控制台程序引用该类库。

这里写图片描述

接下来在DB.Sqlserver命名空间下的DBHelper类添加查询方法

 public List<T> QueryDoMain<T>()
        {
            conn.Open();
            Type type = typeof(T);  //定义T类型的Type对象

            string[] propertiesArray = new string[] { }; //表中的字段数组
            List<string> strList = new List<string>(propertiesArray);
            foreach (var proper in type.GetProperties())  //遍历获取该Type下的所有属性
            {
                strList.Add(proper.Name);
            }
            propertiesArray = strList.ToArray();


            string columns = String.Join(",", propertiesArray);//对字段数组中个元素用逗号拼接成字符串
            string sql = string.Format("select {0} from {1} ", columns, type.Name);

            SqlDataAdapter adapter = new SqlDataAdapter(sql, conn);
            DataTable dt = new DataTable();
            adapter.Fill(dt);


            T t = default(T); //创建T类的对象 并赋值T类型变量的默认值
            List<T> tList = new List<T>();  //创建T类型的List
            for (int i = 0; i < dt.Rows.Count; i++)  //遍历查询结果
            {
                t = (T)Activator.CreateInstance(type);
                foreach (var proper in type.GetProperties())
                {
                    proper.SetValue(t, dt.Rows[i][proper.Name], null);
                }
                tList.Add(t);  //实例化多个T类的对象 并添加到List中
                t = default(T);
            }
            return tList;

        }

然后再控制台调用DBHelper类中的该方法

DBHelper dbHelper = new DBHelper();
List<Employee> employeeList =  dbHelper.QueryDoMain<Employee>();//调用泛型方法
发布了19 篇原创文章 · 获赞 6 · 访问量 9434

猜你喜欢

转载自blog.csdn.net/u012712556/article/details/79340073