C#高级特性(反射)

本文详细介绍了C#中反射的应用,包括如何动态加载类库、获取类型、属性、各种方法(如普通方法、带参数的方法、重载方法、泛型方法、私有方法和静态方法)的具体步骤。

今天来讲解反射的应用:

一、反射是什么?
简诉一下,反射就是.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.ModelinDebugReflection.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.ModelinDebugReflection.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.ModelinDebugReflection.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.ModelinDebugReflection.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.ModelinDebugReflection.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.ModelinDebugReflection.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.ModelinDebugReflection.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;
            }
        }
    }
}

五、结束语:所有的成功都离不开努力,不要用不公平掩饰你不努力的样子
所有的成功都离不开努力,不要用不公平掩饰你不努力的样子

我自是年少,韶华倾负。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

大富大贵7

很高兴能够帮助到你 感谢打赏

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值