利用lambda表达式树优化反射详解

2020-01-05 10:10:10丽君

前言

本节重点不讲反射机制,而是讲lambda表达式树来替代反射中常用的获取属性和方法,来达到相同的效果但却比反射高效。

每个人都知道,用反射调用一个方法或者对属性执行SetValue和GetValue操作的时候都会比直接调用慢很多,这其中设计到CLR中内部的处理,不做深究。然而,我们在某些情况下又无法不使用反射,比如:在一个ORM框架中,你要将一个DataRow转化为一个对象,但你又不清楚该对象有什么属性,这时候你就需要写一个通用的泛型方法来处理,以下代码写得有点恶心,但不妨碍理解意思:


//将DataReader转化为一个对象
     private static T GetObj<T>(SqliteDataReader reader) where T : class
 {
  T obj = new T();
  PropertyInfo[] pros = obj.GetType().GetProperties();
  foreach (PropertyInfo item in pros)
  {
  try
  {
   Int32 Index = reader.GetOrdinal(item.Name);
   String result = reader.GetString(Index);
   if (typeof(String) == item.PropertyType)
   {
   item.SetValue(obj, result);
   continue;
   }
   if (typeof(DateTime) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToDateTime(result));
   continue;
   }
   if (typeof(Boolean) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToBoolean(result));
   continue;
   }
   if (typeof(Int32) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToInt32(result));
   continue;
   }
   if (typeof(Single) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToSingle(result));
   continue;
   }
   if (typeof(Single) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToSingle(result));
   continue;
   }
   if (typeof(Double) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToDouble(result));
   continue;
   }
   if (typeof(Decimal) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToDecimal(result));
   continue;
   }
   if (typeof(Byte) == item.PropertyType)
   {
   item.SetValue(obj, Convert.ToByte(result));
   continue;
   }
  }
  catch (ArgumentOutOfRangeException ex)
  {
   continue;
  }
  }
  return obj;
 }

对于这种情况,其执行效率是特别低下的,具体多慢在下面例子会在.Net Core平台上和.Net Framework4.0运行测试案例.对于以上我举例的情况,效率上我们还可以得到提升。但对于想在运行时修改一下属性的名称或其他操作,反射还是一项特别的神器,因此在某些情况下反射还是无法避免的。