我有一个梦想,是改变世界,这是很多技术人员的梦想;从小事做起,踏实做人做事,当身边的人或事因为自己能像更好的方向改变或发展的时候,那就是在改变世界,至花甲之时,可能我的梦想也无法实现,但我会一直追逐着他前行。我相信蝴蝶效应。荣耀的背后可这一道孤独。一起学习,一起进步。
反射是.NetFrameWork提供给我们的一个帮助类库Reflection.dll
它可以动态加载、解析、使用dll
普通方法我们使用时项目中添加引用,然后实例化使用;
反射基于“元数据”–metadata
Reflection.dll可以读取元数据,然后知道了dll中的方法、属性,则可以调用
以下代码实现了依赖接口,实现可配置、可扩展的动态的加载dll并调用方法(通过接口实现)
比如现在如下的代码实现的是sqlserver的操作,如果我编写了一个Oracle数据库操作的dll继承自IDBHelper,通过配置,那么我就可以实现不变更代码的情况下,实现了通过配置扩展了程序。
配置文件如下:
<add key="DbHelper" value="SqlserverHelperLib.SqlserverHelper,SqlserverHelperLib"/>
代码如下
using System;
using System.Configuration;
using System.Reflection;
using SqlserverHelperLib;
namespace Reflaction
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Reflection的学习");
//--------------原始方法------------------
//引用了SqlserverHelperLib.dll,如果去除了SqlServerHelperLib的引用,那么会导致对象无法创建
var helperOld = new SqlserverHelper();
helperOld.Query(@"old");
Console.WriteLine();
var config = ConfigurationManager.AppSettings["DbHelper"];
var myClass = config.Split(',')[0];
var myNnamspace = config.Split(',')[1];
//动态加载dll
var assembly = Assembly.Load(myNnamspace);
//创建对象
//不用引用SqlserverHelperLib.dll,因为SqlserverHelperLib.dll引用了IDbHelper接口,直接引用接口就行,也能够实现动态加载dll
//基于类的完整名称(命名空间.类名)找出类型
var type = assembly.GetType(myClass);
//根据类型创建对象
var myObj =Activator.CreateInstance(type);
//强制转化为具体类型对象
var helperReflection = (IDbHelperLib.IDbHelper) myObj;
helperReflection.Query("Reflection");
Console.ReadLine();
}
}
}
以下代码实现了不依赖接口,实现可配置、可扩展的动态的加载dll
调用普通方法、调用重载方法、调用私有方法、破坏单例
using System;
using System.Configuration;
using System.Reflection;
namespace Reflaction
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Reflection的学习");
var config = ConfigurationManager.AppSettings["DbHelper"];
var myClass = config.Split(',')[0];
var myNnamspace = config.Split(',')[1];
//动态加载dll
var assembly = Assembly.Load(myNnamspace);
//创建对象
//不用引用SqlserverHelperLib.dll,因为SqlserverHelperLib.dll引用了IDbHelper接口,直接引用接口就行,也能够实现动态加载dll
//基于类的完整名称(命名空间.类名)找出类型
var type = assembly.GetType(myClass);
//根据类型创建对象
var myObj = Activator.CreateInstance(type);
//获取\调用方法
var method = type.GetMethod("Query");
method.Invoke(myObj, new object[] { "不依赖接口Relection" });
//获取\调用重载方法
var method1 = type.GetMethod("Query1", new Type[] { typeof(string) });
method1.Invoke(myObj, new object[] { "不依赖接口Relection1" });
//获取\调用重载方法
var method12 = type.GetMethod("Query1", new Type[] { typeof(int) });
method12.Invoke(myObj, new object[] { 1 });
//获取\调用私有方法
var method2 = type.GetMethod("Query2", BindingFlags.NonPublic|BindingFlags.Public|BindingFlags.Instance);
method2.Invoke(myObj, new object[] { "不依赖接口Relection" });
//使用反射破坏单例--如下代码会实现一次对象的创建,不管你是否时单例,所以破坏了单例(因为单例时不可以创建对象的)
//var myObj = Activator.CreateInstance(type,true);
Console.ReadLine();
}
}
}
以下代码实现了基于反射实现的简单数据库访问层
调用类
var helper = new SqlserverHelper();
var people = helper.QueryDomain<People>();
数据库操作封装
public T QueryDomain<T>()
{
var id = 1;
//获取类型
var type = typeof(T);
//获取该类型对象
var obj = (T)Activator.CreateInstance(type);
foreach (var prop in type.GetProperties())
{
Console.WriteLine("属性名称:{0}", prop.Name);
}
var columns = string.Join(",", type.GetProperties().Select(prop => string.Format("[{0}]", prop.Name)));
string sql = string.Format("SELECT {0} FROM {1} WHERE ID={2}", columns, type.Name, id);
using (var con = new SqlConnection(ConStr))
{
var cmd = new SqlCommand(sql, con);
con.Open();
var reader = cmd.ExecuteReader(CommandBehavior.CloseConnection);
if (reader.Read())
{
//获取属性并赋值
foreach (var prop in type.GetProperties())
{
//获取属性名称
var propName = prop.Name;
prop.SetValue(obj, reader[propName], null);
Console.WriteLine("属性名称:{0},值:{1}", prop.Name, prop.GetValue(obj, null));
}
}
}
return obj;
}