2语法基础_反射,表达式目录树

什么反射:1.通过微软提供的类,让我们可以直接在代码里面访问已经编译好的DLL

      2.在c#编码中 想动态=反射+配置文件 

  

ORM:就是在c#里面把数据库的表直接当做对象来操作使用

1:反射的定义:微软提供的一个帮助类库,为了让我们不用在vs里面添加引用从而直接动态加载dll 去用里面的方法  

2:反射的应用领域:MVC  AOP  IOC  ORM  Attribute  都是使用了反射

反射特点:
动态 减少对象和对象之间的依赖,只需要知道类名(字符串)、方法名(字符串),就可以调用,
还可以突破特定权限,可以做到普通方式无法做到的
编写比较困难,代码量大,编写的时候容易出错
性能问题,性能损耗大, 可以进行缓存优化,但是还是会相差十多倍的性能

3:表达式目绿树本质就是一种数据结构(二叉树),如m*n+2+x 会从右往左拆分成 >(M*n+2)+x>(M*n)+2>M*n

  拉姆达表达式是作为委托的一个参数,本质就是一个匿名方法,它只不过是可以快捷的声明表达式目绿树

  表达式目录树的作用:

    1.SQL查询语句拼接, (之前写sql查询条件都是根据一个个条件进行判断拼接,) 使用表达式目录树可以动态拼接

    2.类与类之间的转换,使用表达式目录树把A类变成一个新的B类(结构要相同)

      一般实现方法:1.硬编码(写死),2.json序列化,3.表达式目录树

    3.使用表达式目录树动态转换类,和硬编码性能几乎没啥差距

      (这里使用反射还有性能问题)   使用反射获取到A类的属性和字段, 用表达式目录树拼接好一个新的B类

                      然后使用委托执行B类,

      (使用泛型泛型解决反射性能问题)最后使用泛型缓存 存储每个执行的委托(泛型缓存:为每个不同类型生成副本,所以不同类型只需要执行一次委托,后面就直接从缓存里面取) 

     这样性能高,扩展性好,又解决了反射的性能问题,

  

 

 

 

4:使用反射创建对象:反射+简单工厂+配置文件 实现简单数据库访问

 Console.WriteLine("最基本使用反射调用类方法");
                    // 1、动态加载
                    Assembly assembly = Assembly.Load("类库");// dll名称  默认到当前目录下查找
                    //2、获取类型
                    Type type = assembly.GetType("类库.类");
                    //3、创建对象
                    object oDbHelper = Activator.CreateInstance(type);

                    dynamic dDbHelper = Activator.CreateInstance(type);
                    dDbHelper.Query(); //dynamic 是一个动态类型,可以避开编译器的检查,运行时检查  存在安全问题 因为c#是强类型语言,一般在编译时就会检测
                    //4、类型转换
                    IDBHelper iDBHelper = oDbHelper as IDBHelper;
                    //5、调用方法
                    iDBHelper.Query();
最基本使用反射调用类方法
                    Assembly assembly = Assembly.Load("类库");
                    Type type = assembly.GetType("类库.类名");
                    object oTest = Activator.CreateInstance(type);

                    MethodInfo show1 = type.GetMethod("Show1");
                    //得到方法
                    //调用方法为什么一定要类型转换? 
                    //需要先获取方法,然后方法Invoke
                    show1.Invoke(oTest, new object[0]);// 反射调用方法 
反射调用类.方法
   //泛型编译之后生成占位符  `1   `2    `3
                    //正常调用
                    GenericMethod genericMethod = new GenericMethod();
                    genericMethod.Show<int, string, DateTime>(1234, "", DateTime.Now);

                    //使用反射调用
                    Assembly assembly = Assembly.Load("类库");
                    Type type = assembly.GetType("类库.类名");
                    object oTest = Activator.CreateInstance(type);
                    MethodInfo genericMethod = type.GetMethod("Show");
                    MethodInfo genericMethod1 = genericMethod.MakeGenericMethod(new Type[] { typeof(int), typeof(string), typeof(DateTime) });// 指定泛型方法的  具体参数 
                    genericMethod1.Invoke(oTest, new object[] { 123, "11", DateTime.Now }); // 传入参数必须和声明的一样
反射调用泛型方法
private static string Customers = ConfigurationManager.ConnectionStrings["Customers"].ToString();

        /// <summary>
        /// 泛型方法
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="id"></param>
        /// <returns></returns>
        public static T Find<T>(int id)   
        {
            //string sql = @"SELECT   [Id]
            //      ,[Name]
            //      ,[CreateTime]
            //      ,[CreatorId]
            //      ,[LastModifierId]
            //      ,[LastModifyTime]
            //  FROM [SystemDB].[dbo].[Company] where Id=" + id;

            Type type = typeof(T);
            object oCompany = Activator.CreateInstance(type);
            //List<string> 
            var propNames = type.GetProperties().Select(a => $"[{a.Name}]");
            string props = string.Join(",", propNames);
            string sql = $"SELECT {props } FROM [{type.Name}] where Id={id}"; 
            using (SqlConnection connection = new SqlConnection(Customers))
            {
                SqlCommand sqlCommand = new SqlCommand(sql, connection);
                connection.Open();
                SqlDataReader reader = sqlCommand.ExecuteReader();
                if (reader.Read()) //开始读取
                {
                    foreach (var prop in type.GetProperties())
                    {
                        prop.SetValue(oCompany, reader[prop.Name]);
                    }
                }
            }
            return (T)oCompany;
        }
反射+泛型 实现通用简单数据库访问

 

   Assembly assembly = Assembly.Load("类库");
                    Type type = assembly.GetType("类库。类名");

                    //Activator.CreateInstance 
                    object oDbHelper = Activator.CreateInstance(type);
                    object oDbHelper1 = Activator.CreateInstance(type, new object[] { "杰克" });
                    object oDbHelper2 = Activator.CreateInstance(type, new object[] { "我是谁" });
                    object oDbHelper3 = Activator.CreateInstance(type, new object[] { 123 });
                }
反射选择不同的构造函数创建对象

 

  

 

 

 

 

posted @ 2020-05-25 15:44  12不懂3  阅读(267)  评论(0编辑  收藏  举报
创作不易,请勿抄袭,欢迎转载!