- A+
所属分类:.NET技术
今天来讲解反射的应用:
一、反射是什么?
简诉一下,反射就是.Net Framework 的一个帮助类库,可以获取并使用metadata(元数据清单);说的通俗易懂点,就是不用通过引用,仍然可以使用其他层的类。
二、让我们建一个项目来开始操作吧!!!
1、建立一个控制台应用程序,并建立一个类库,类库里添加一个用户类。
public class UsersInfo { public string Name { get; set; } public bool Sex { get; set; } public void CommonMethod() { Console.WriteLine("我是普通方法"); } public void ParameterMethod(string name) { Console.WriteLine("我是带参数方法,我叫"+name); } public void OverrideMethod(int age) { Console.WriteLine("我是重载方法,我今年"+age); } public void OverrideMethod(string name) { Console.WriteLine("我是重载方法,我叫" + name); } public void GenericityMethod<T>(T t) { Console.WriteLine("我是泛型方法方法,类型是"+typeof(T)); } private void PrivateMethod() { Console.WriteLine("我是私有方法"); } public static void StaticMethod() { Console.WriteLine("我是静态方法"); } }
2、利用反射获取类库,和类
- 第一步引用命名空间
- 第二步,动态加载类库,写要获取类库的绝对路径
- 第三步,动态获取类型,写类库的名称和类的名称,不需要后缀
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); } } } }
3、利用反射获取属性,和属性类型
- 遍历类型的属性集合
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } } } } }
三、获取方法(方法类型比较多,所以单独做个模块来写)
- 创建一个符合类型的对象
- 指定要获取的方法名称
- 创建方法,第一个参数,对象,第二个参数,没有则为空
1、获取普通方法
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } Console.WriteLine("***********************普通方法*****************************"); object oUser = Activator.CreateInstance(type);//创建一个符合类型的对象 MethodInfo method = type.GetMethod("CommonMethod");//指定要获取的方法名称 method.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,没有则为空 } } } }
2、获取带参数的方法
- 指定要获取的方法名称
- 创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } Console.WriteLine("***********************普通方法*****************************"); object oUser = Activator.CreateInstance(type);//创建一个符合类型的对象 MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要获取的方法名称 commonMethod.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,没有则为空 Console.WriteLine("***********************带参数的方法*****************************"); MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要获取的方法名称 parameterMethod.Invoke(oUser, new object[] { "餐餐"});//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 } } } }
3、重载方法
- 指定要获取的方法名称,和参数类型
- 创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } Console.WriteLine("***********************普通方法*****************************"); object oUser = Activator.CreateInstance(type);//创建一个符合类型的对象 MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要获取的方法名称 commonMethod.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,没有则为空 Console.WriteLine("***********************带参数的方法*****************************"); MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要获取的方法名称 parameterMethod.Invoke(oUser, new object[] { "餐餐"});//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法int参数*****************************"); MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要获取的方法名称,和参数类型 overrideMethodInt.Invoke(oUser, new object[] { 18 });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法string参数*****************************"); MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要获取的方法名称,和参数类型 overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 } } } }
4、泛型方法
- 指定要获取的方法名称,和泛型参数类型
- 创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } Console.WriteLine("***********************普通方法*****************************"); object oUser = Activator.CreateInstance(type);//创建一个符合类型的对象 MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要获取的方法名称 commonMethod.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,没有则为空 Console.WriteLine("***********************带参数的方法*****************************"); MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要获取的方法名称 parameterMethod.Invoke(oUser, new object[] { "餐餐"});//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法int参数*****************************"); MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要获取的方法名称,和参数类型 overrideMethodInt.Invoke(oUser, new object[] { 18 });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法string参数*****************************"); MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要获取的方法名称,和参数类型 overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************泛型方法*****************************"); MethodInfo genericityMethod = type.GetMethod("GenericityMethod").MakeGenericMethod(new Type[] {typeof(int)});//指定要获取的方法名称,和泛型参数类型 genericityMethod.Invoke(oUser, new object[] { 123 });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 } } } }
5、私有方法
- 指定要获取的方法名称,指明是父类的私有方法
- 创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Reflection;//第一步引用命名空间 namespace Reflection { class Program { static void Main(string[] args) { { Console.WriteLine("***********************获取类*****************************"); //第二步,动态加载类库,写要获取类库的绝对路径 Assembly assembly= Assembly.LoadFile(@"C:Users炸天张缺缺DesktopReflectionReflection.ModelbinDebugReflection.Model.dll"); //第三步,动态获取类型,写类库的名称和类的名称,不需要后缀 Type type = assembly.GetType("Reflection.Model.UsersInfo"); Console.WriteLine(type.Name); Console.WriteLine("***********************获取属性*****************************"); //遍历类型的属性集合 foreach (var item in type.GetProperties()) { Console.WriteLine(item.Name+" "+item.PropertyType); } Console.WriteLine("***********************普通方法*****************************"); object oUser = Activator.CreateInstance(type);//创建一个符合类型的对象 MethodInfo commonMethod = type.GetMethod("CommonMethod");//指定要获取的方法名称 commonMethod.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,没有则为空 Console.WriteLine("***********************带参数的方法*****************************"); MethodInfo parameterMethod = type.GetMethod("ParameterMethod");//指定要获取的方法名称 parameterMethod.Invoke(oUser, new object[] { "餐餐"});//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法int参数*****************************"); MethodInfo overrideMethodInt = type.GetMethod("OverrideMethod",new Type[] { typeof(int)});//指定要获取的方法名称,和参数类型 overrideMethodInt.Invoke(oUser, new object[] { 18 });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************重载方法string参数*****************************"); MethodInfo overrideMethodStrint = type.GetMethod("OverrideMethod", new Type[] { typeof(string) });//指定要获取的方法名称,和参数类型 overrideMethodStrint.Invoke(oUser, new object[] { "餐餐" });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************泛型方法*****************************"); MethodInfo genericityMethod = type.GetMethod("GenericityMethod").MakeGenericMethod(new Type[] {typeof(int)});//指定要获取的方法名称,和泛型参数类型 genericityMethod.Invoke(oUser, new object[] { 123 });//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 Console.WriteLine("***********************泛型方法*****************************"); MethodInfo privateMethod = type.GetMethod("PrivateMethod",BindingFlags.Instance|BindingFlags.NonPublic);//指定要获取的方法名称,指明是父类的私有方法 privateMethod.Invoke(oUser,null);//创建方法,第一个参数,对象,第二个参数,是一个object对象数组,写对应的参数类型 } } } }
6、静态方法
Console.WriteLine("***********************静态方法*****************************"); MethodInfo staticMethod = type.GetMethod("StaticMethod");//指定要获取的方法名称 staticMethod.Invoke(null, null);//不需要实例化,所以第一个可以不写,为空
四、小扩展,反射书写ORM(请原谅我没有注释)
接口
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; namespace NineMonthExam.IDAL { public interface IEFHelpers<T> where T:class { bool Add(T t); bool Remove(int id); bool Edit(T t); List<T> GetAll(); } }
dbhelp类
using NineMonthExam.IDAL; using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Configuration; using System.Data.SqlClient; using NineMonthExam.Model; namespace NineMonthExam.DAL { public class DBHelpers<T> : IEFHelpers<T> where T : BaseModel { private static Type type; private static string typeName; private static string nameStr; private static string noIdNameStr; private static string sql = ""; private static StringBuilder addStr = new StringBuilder(); private static StringBuilder getStr = new StringBuilder(); private static StringBuilder removeStr = new StringBuilder(); private static StringBuilder modify = new StringBuilder(); private static StringBuilder modifyStr = new StringBuilder(); private static string conStr=ConfigurationManager.ConnectionStrings["conStr"].ConnectionString; static DBHelpers() { type = typeof(T); typeName = type.Name; nameStr =string.Join(",", type.GetProperties().Select(m=>m.Name)); noIdNameStr = string.Join(",", type.GetProperties().Where(m=>!m.Name.Equals("Id")).Select(m => m.Name)); addStr.Append($@"insert into {typeName} ({noIdNameStr}) values ({string.Join(",", type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m =>$"@{m.Name}"))})"); getStr.Append($@"select {nameStr} from {typeName}"); removeStr.Append($@"delete from {typeName}"); modify.Append($@"update {typeName} set"); foreach (var item in type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m => m.Name)) { modify.Append($@" {item}=@{item},"); } string qian = modify.ToString(); qian = qian.Remove(qian.LastIndexOf(',')); modifyStr.Append(qian); } public bool Add(T t) { SqlParameter[] parameters = type.GetProperties().Where(m => !m.Name.Equals("Id")).Select(m => new SqlParameter($"@{m.Name}", m.GetValue(t) ?? DBNull.Value)).ToArray(); sql = addStr.ToString(); using (SqlConnection conn = new SqlConnection(conStr)) { conn.Open(); SqlCommand com = new SqlCommand(sql,conn); com.Parameters.AddRange(parameters); return com.ExecuteNonQuery() > 0; } } public bool Edit(T t) { SqlParameter[] parameters = type.GetProperties().Select(m => new SqlParameter($"@{m.Name}", m.GetValue(t)??DBNull.Value)).ToArray(); string edit=$" where Id = @{type.GetProperty("Id").Name}"; sql = modifyStr.ToString()+ edit; using (SqlConnection conn = new SqlConnection(conStr)) { conn.Open(); SqlCommand com = new SqlCommand(sql, conn); com.Parameters.AddRange(parameters); return com.ExecuteNonQuery() > 0; } } private T GetT(SqlDataReader sdr) { T obj = Activator.CreateInstance(type) as T; foreach (var item in type.GetProperties()) { if (sdr[item.Name].GetType() != typeof(DBNull)) { item.SetValue(obj, sdr[item.Name]); } else { item.SetValue(obj, null); } } return obj; } public List<T> GetAll() { sql = getStr.ToString(); using (SqlConnection conn = new SqlConnection(conStr)) { conn.Open(); SqlCommand com = new SqlCommand(sql, conn); SqlDataReader reader =com.ExecuteReader(); List<T> list = new List<T>(); while (reader.Read()) { list.Add(GetT(reader)); } return list; } } public bool Remove(int id) { string del=$" where Id = {id}"; sql = removeStr.ToString()+del; using (SqlConnection conn = new SqlConnection(conStr)) { conn.Open(); SqlCommand com = new SqlCommand(sql, conn); return com.ExecuteNonQuery() > 0; } } } }
五、结束语:所有的成功都离不开努力,不要用不公平掩饰你不努力的样子
所有的成功都离不开努力,不要用不公平掩饰你不努力的样子