日本免费精品_最新日韩一区_亚洲视频一区在线_a在线视频观看_天天射夜夜骑_粉嫩av一区二区三区_欧美中日韩免费视频_综合图区欧美_国内精品美女在线观看_午夜精品久久久久久久男人的天堂

首頁 > 編程 > C# > 正文

利用lambda表達式樹優化反射詳解

2019-10-29 19:41:08
字體:
來源:轉載
供稿:網友

前言

本節重點不講反射機制,而是講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運行測試案例.對于以上我舉例的情況,效率上我們還可以得到提升。但對于想在運行時修改一下屬性的名稱或其他操作,反射還是一項特別的神器,因此在某些情況下反射還是無法避免的。

但是對于只是簡單的SetValue或者GetValue,包括用反射構造函數,我們可以想一個中繼的方法,那就是使用表達式樹。對于不理解表達式樹的,可以到微軟文檔查看,點擊我。表達式樹很容易通過對象模型表示表達式,因此強烈建議學習。查看以下代碼:

static void Main() {  Dog dog = new Dog();  PropertyInfo propertyInfo = dog.GetType().GetProperty(nameof(dog.Name)); //獲取對象Dog的屬性  MethodInfo SetterMethodInfo = propertyInfo.GetSetMethod(); //獲取屬性Name的set方法  ParameterExpression param = Expression.Parameter(typeof(Dog), "param");  Expression GetPropertyValueExp = Expression.Lambda(Expression.Property(param, nameof(dog.Name)), param);  Expression<Func<Dog, String>> GetPropertyValueLambda = (Expression<Func<Dog, String>>)GetPropertyValueExp;  ParameterExpression paramo = Expression.Parameter(typeof(Dog), "param");  ParameterExpression parami = Expression.Parameter(typeof(String), "newvalue");  MethodCallExpression MethodCallSetterOfProperty = Expression.Call(paramo, SetterMethodInfo, parami);  Expression SetPropertyValueExp = Expression.Lambda(MethodCallSetterOfProperty, paramo, parami);  Expression<Action<Dog, String>> SetPropertyValueLambda = (Expression<Action<Dog, String>>)SetPropertyValueExp;  //創建了屬性Name的Get方法表達式和Set方法表達式,當然只是最簡單的  Func<Dog, String> Getter = GetPropertyValueLambda.Compile();   Action<Dog, String> Setter = SetPropertyValueLambda.Compile();  Setter?.Invoke(dog, "WLJ"); //我們現在對dog這個對象的Name屬性賦值  String dogName = Getter?.Invoke(dog); //獲取屬性Name的值    Console.WriteLine(dogName);  Console.ReadKey(); } public class Dog {  public String Name { get; set; } }

以下代碼可能很難看得懂,但只要知道我們創建了屬性的Get、Set這兩個方法就行,其結果最后也能輸出狗的名字 WLJ,擁有ExpressionTree的好處是他有一個名為Compile()的方法,它創建一個代表表達式的代碼塊。現在是最有趣的部分,假設你在編譯時不知道類型(在這篇文章中包含的代碼我在不同的程序集上創建了一個類型)你仍然可以應用這種技術,我將對于常用的屬性的set,get操作進行分裝。

/// <summary>   /// 屬性類,仿造反射中的PropertyInfo /// </summary>   public class Property {  private readonly PropertyGetter getter;  private readonly PropertySetter setter;  public String Name { get; private set; }  public PropertyInfo Info { get; private set; }  public Property(PropertyInfo propertyInfo)  {   if (propertyInfo == null)    throw new NullReferenceException("屬性不能為空");   this.Name = propertyInfo.Name;   this.Info = propertyInfo;   if (this.Info.CanRead)   {    this.getter = new PropertyGetter(propertyInfo);   }   if (this.Info.CanWrite)   {    this.setter = new PropertySetter(propertyInfo);   }  }  /// <summary>     /// 獲取對象的值  /// </summary>    /// <param name="instance"></param>    /// <returns></returns>     public Object GetValue(Object instance)  {   return getter?.Invoke(instance);  }  /// <summary>     /// 賦值操作  /// </summary>    /// <param name="instance"></param>    /// <param name="value"></param>     public void SetValue(Object instance, Object value)  {   this.setter?.Invoke(instance, value);  }  private static readonly ConcurrentDictionary<Type, Core.Reflection.Property[]> securityCache = new ConcurrentDictionary<Type, Property[]>();  public static Core.Reflection.Property[] GetProperties(Type type)  {   return securityCache.GetOrAdd(type, t => t.GetProperties().Select(p => new Property(p)).ToArray());  } }  /// <summary>   /// 屬性Get操作類  /// </summary>    public class PropertyGetter  {  private readonly Func<Object, Object> funcGet;  public PropertyGetter(PropertyInfo propertyInfo) : this(propertyInfo?.DeclaringType, propertyInfo.Name)  {  }  public PropertyGetter(Type declareType, String propertyName)  {   if (declareType == null)   {    throw new ArgumentNullException(nameof(declareType));   }   if (propertyName == null)   {    throw new ArgumentNullException(nameof(propertyName));   }   this.funcGet = CreateGetValueDeleagte(declareType, propertyName);  }  //代碼核心部分     private static Func<Object, Object> CreateGetValueDeleagte(Type declareType, String propertyName)  {   // (object instance) => (object)((declaringType)instance).propertyName       var param_instance = Expression.Parameter(typeof(Object));   var body_objToType = Expression.Convert(param_instance, declareType);   var body_getTypeProperty = Expression.Property(body_objToType, propertyName);   var body_return = Expression.Convert(body_getTypeProperty, typeof(Object));   return Expression.Lambda<Func<Object, Object>>(body_return, param_instance).Compile();  }  public Object Invoke(Object instance)  {   return this.funcGet?.Invoke(instance);  } }  public class PropertySetter {  private readonly Action<Object, Object> setFunc;  public PropertySetter(PropertyInfo property)   {   if (property == null)   {    throw new ArgumentNullException(nameof(property));   }   this.setFunc = CreateSetValueDelagate(property);  }  private static Action<Object, Object> CreateSetValueDelagate(PropertyInfo property)  {   // (object instance, object value) =>    //  ((instanceType)instance).Set_XXX((propertyType)value)   //聲明方法需要的參數   var param_instance = Expression.Parameter(typeof(Object));   var param_value = Expression.Parameter(typeof(Object));   var body_instance = Expression.Convert(param_instance, property.DeclaringType);   var body_value = Expression.Convert(param_value, property.PropertyType);   var body_call = Expression.Call(body_instance, property.GetSetMethod(), body_value);   return Expression.Lambda<Action<Object, Object>>(body_call, param_instance, param_value).Compile();  }  public void Invoke(Object instance, Object value)  {   this.setFunc?.Invoke(instance, value);  } }

在將代碼應用到實例:

   Dog dog = new Dog();   PropertyInfo propertyInfo = dog.GetType().GetProperty(nameof(dog.Name));      //反射操作   propertyInfo.SetValue(dog, "WLJ");   String result = propertyInfo.GetValue(dog) as String;   Console.WriteLine(result);      //表達式樹的操作   Property property = new Property(propertyInfo);   property.SetValue(dog, "WLJ2");   String result2 = propertyInfo.GetValue(dog) as String;   Console.WriteLine(result2);

發現其實現的目的與反射一致,但效率卻有明顯的提高。

以下測試以下他們兩之間的效率。測試代碼如下:

   Student student = new Student();   PropertyInfo propertyInfo = student.GetType().GetProperty(nameof(student.Name));   Property ExpProperty = new Property(propertyInfo);   Int32 loopCount = 1000000;   CodeTimer.Initialize(); //測試環境初始化   //下面該方法個執行1000000次   CodeTimer.Time("基礎反射", loopCount, () => {     propertyInfo.SetValue(student, "Fode",null);   });   CodeTimer.Time("lambda表達式樹", loopCount, () => {    ExpProperty.SetValue(student, "Fode");   });   CodeTimer.Time("直接賦值", loopCount, () => {    student.Name = "Fode";   });   Console.ReadKey();

其.Net4.0環境下運行結果如下:

lambda,表達式樹,反射

.Net Core環境下運行結果:

lambda,表達式樹,反射

從以上結果可以知道,迭代同樣的次數反射需要183ms,而用表達式只要34ms,直接賦值需要7ms,在效率上,使用表達式這種方法有顯著的提高,您可以看到使用此技術可以完全避免使用反射時的性能損失。反射之所以效率有點低主要取決于其加載的時候時在運行期下,而表達式則在編譯期,下篇有空將會介紹用Emit技術優化反射,會比表達式略快一點。

注:對于常用對象的屬性,最好將其緩存起來,這樣效率會更高。。

代碼下載

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,如果有疑問大家可以留言交流,謝謝大家對VEVB武林網的支持。


注:相關教程知識閱讀請移步到c#教程頻道。
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
在线视频三区| 在线国产1区| 最近中文字幕第一页| 999精品网| 自拍日韩亚洲一区在线| 中文字幕在线观看亚洲| 91精品国产自产在线观看永久∴| 国产日产一区二区| 在线视频不卡国产V| 一二三区精品视频| 欧美日韩成人一区| 亚洲欧美99| 中文字幕在线亚洲| 国产婷婷色一区二区三区| 国产三级视频在线播放线观看| 国产在线视频不卡| 国产一区精品在线| 日韩一级免费视频| 日韩中文首页| 欧美不卡123| 在线欧美日韩精品| 91精品在线视频观看| 国产视频97| 日韩欧美在线视频| 欧美日韩国产免费| 国产视频1区2区| 国产中文在线播放| 日韩精品福利一区二区三区| 日韩精品视频免费在线观看| 人人做人人澡人人爽欧美| 亚洲国产福利视频| 国产一区在线不卡| 日韩在线观看视频一区| 国产乱码在线观看| 久久久精品日韩| 国产欧美日韩在线观看| 欧美日韩999| 欧美日韩一区二区在线视频| 日韩在线观看视频一区| 亚洲美女视频一区| 红桃视频亚洲| 在线三级av| 日本一欧美一欧美一亚洲视频| 亚洲男女av一区二区| 91久久精品在线| 91精品国产调教在线观看| 国产欧美日韩91| 国产v日产∨综合v精品视频| 国产一区精品在线| 中文欧美字幕免费| 日韩视频一区在线观看| 国产蜜臀在线| 国产欧美日韩亚洲| 日韩中文字幕网| 亚洲成在线观看| 精品视频1区2区3区| 日本精品专区| 精品国产免费观看一区| 久久蜜桃一区二区| 综合激情国产一区| 国产一区激情在线| 日韩av一区在线| 日韩欧美中文在线| 中文字幕精品www乱入免费视频| 日韩欧美中文| 精品视频999| 亚洲综合在线视频| 精品日韩视频在线观看| 日本黄色一区二区| 色综合久久88色综合天天免费| 精品日韩欧美在线| 91精品国产91久久久久| 久久激情一区| 91久久久精品国产| 日韩欧美一二三区| 国产成人精品三级| 国产一级久久久| 国产专区中文字幕| 国精品产品一区| 欧美日韩第一| 亚洲电影中文字幕在线观看| 日韩在线观看精品| 在线视频一区二区三区在线播放 | 久久99精品久久久久婷婷| 国产拍揄自揄精品视频麻豆| 亚洲一区日韩精品中文字幕| 中文字幕精品视频在线| aa国产成人| 一区二区三区精品99久久| 国产日韩成人精品| 国产日韩中文在线| 国产在线www| 日韩三级高清在线| 亚洲中文字幕在线一区| 欧美日韩国产免费观看视频| av免费在线不卡| 欧美日韩在线播放三区四区| 欧美日韩在线国产| 亚洲素人一区二区| 精品久久久网| 欧美国产小视频| 国产视频97| 日韩在线视频观看| 色猫猫国产区一区二在线视频 | www中文字幕| 91精品在线看V| 色综合久久六月婷婷中文字幕| 第一页在线观看| 91精品在线国产| 亚洲高清视频在线| 国产在线日韩欧美| 色综合天天综合网天天狠天天| 日韩在线不卡| 午夜亚洲福利| 日本精品在线播放| 国产99亚洲| 亚洲最新免费视频| 欧美久久久精品| 久久精品www| 日韩在线视频一区| 日韩精品视频在线观看视频| 91精品国产色综合久久久蜜香臀| 亚洲第一中文字幕在线观看| 精品视频—区二区三区免费| 精品网站999www| 日韩av一区在线| 91精品国产综合久久久久久| 欧美亚洲视频在线看网址| 91精品视频在线| 国产欧美日韩中文字幕| 国产三级在线播放| 91蜜桃在线视频| 在线欧美日韩精品| 欧美中文字幕第一页| 蜜桃视频中文字幕| 亚洲第一视频| 亚洲人成欧美中文字幕| 欧美中日韩在线| 中文字幕在线观看播放| 亚洲 欧美综合在线网络| 国产欧美日韩中文字幕在线| 在线视频一区二区三区在线播放| 国产91欧美| 中文字幕在线观看国产| 欧美日韩视频免费看| 在线不卡一区二区| 中文字幕亚洲高清| 精品久久91| av中文在线播放| 日韩精品视频免费| 亚洲热在线观看| 午夜精品一区二区三区免费视频| 中文字幕亚洲乱码| 亚洲欧洲在线观看av| 92久久精品| 91精品综合久久| 欧美日韩国产首页| 中文字幕在线观看精品| 久久麻豆视频| 成人xxxx| 久久久综合av| 精品日韩欧美在线| www.尤物.com| 久久精品久久久久| 日韩视频一区| 一区二区精品区| 欧美日韩在线视频免费观看 | 亚洲乱码在线观看| 国产婷婷一区二区| 欧美成人vr18sexvr| 中文网丁香综合网| 一本一道综合狠狠老| 一区二区三区精品久久久| 国精品产品一区| 日韩欧美中文字幕在线观看| 精品日本视频| 中文字幕一区二区三区精品| 国产 欧美在线| 亚洲欧美中文字幕| 日韩免费电影网站| 中文字幕日韩视频| 日韩av一区二| 91精品国产91久久久久久三级| 不卡一区二区三区视频| 日韩在线视频二区| 日韩欧美高清在线视频| 91麻豆视频网站| 一区二区欧美国产| 91精品免费观看| 精品综合久久久久| 亚洲 欧美 中文字幕| 国产三级视频在线播放线观看| 午夜国产视频 | 日本精品在线中文字幕| 欧美日韩尤物久久| 欧美日韩国产在线观看| 亚洲日本欧美日韩高观看| 久久69成人| 国产999在线观看| 亚洲视频 中文字幕| 99综合精品久久| 婷婷久久综合九色国产成人| 欧美日本精品在线| 亚洲视频一二三四| 久久69成人| 欧美日韩在线观看成人| 中文字幕无线码一区| 亚洲免费精品| 中文字幕不卡三区| 最近中文字幕在线中文高清版| 在线精品视频免费播放| 国产黄色在线免费观看| 亚洲 欧美综合在线网络| 国产91久久久久蜜臀青青天草二 | 久久夜色精品国产噜噜亚洲av| 日本精品在线中文字幕| 精品视频在线视频| 欧美不卡一区二区| 91久久在线| 国产一级片在线| 国产欧美日韩精品综合| 亚洲高清在线观看一区| 婷婷精品进入| 国产最顶级的黄色片在线免费观看| 国产欧美日韩三级| 亚洲三级免费看| 日韩视频一区二区在线观看| 欧美三级一区二区三区| 国产一区高清视频| 欧美日韩三级在线观看| 欧美日韩精品不卡| 欧美一级日韩不卡播放免费 | 国产中文在线播放| 国产视频中文字幕在线观看| 国产香蕉精品视频| 中文字幕在线欧美| 视频一区二区精品的福利| 国产欧美在线观看| 丰满少妇一区二区| 亚洲高清视频一区| 国产区日韩欧美| 久久中文免费视频| 午夜av一区二区| 久久在线91| aa国产成人| 精品一二三四| 天堂在线中文资源| 亚洲欧美中文字幕在线观看| 精品国产乱码一区二区| 精品乱子伦一区二区| 欧美日韩综合在线观看| 国产卡1卡2卡三卡在线| 国产丝袜一区二区| 日韩中文在线字幕| 黄色国产网站在线播放| 国产福利一区二区精品秒拍| 国产成人精品三级| 亚洲一二三不卡| 日韩视频一区在线观看| 99精品一级欧美片免费播放| 中文字幕五月天| 亚洲三级av| 欧美日韩久久不卡| 成人xxxx| 在线精品日韩| 午夜亚洲一区| 欧美日韩性视频| 国产一级一片免费播放| 日韩精品视频在线| 国产69精品久久app免费版| 欧美日韩亚洲国内综合网俺| 日韩精品大片| 欧美日韩一级黄| 亚洲黄色一区二区| 亚洲成av人片在线| 国产区在线看| 国产123在线| 五月综合激情日本mⅴ| 激情婷婷亚洲| 国产在线二区| 日韩国产高清一区| 国产午夜精品视频| 久久精品99国产国产精| 婷婷久久综合网| 在线视频不卡一区二区| 国产一区三区三区| 精品视频在线导航| 正在播放日韩精品| 国产在线www| 中文字幕亚洲免费| 天天摸日日摸狠狠添| 欧美日韩日本视频| 国产婷婷色一区二区三区| 亚洲3区在线| 日韩美女视频一区二区在线观看| av最新网址| 不卡一二三区| 国产激情在线播放| 欧美日韩午夜在线视频| 欧美在线日韩| 久久精品不卡| 日韩国产在线观看一区| 久久精品99国产国产精| 欧美不卡一区二区| 在线综合 亚洲 欧美中文字幕| 精品视频国产| 91精品国产入口| 日韩在线小视频| 欧美日韩乱国产| 国产手机精品视频| 91精品久久久久| 极品久久久久久| 日韩综合精品| 中文字幕在线精品| 欧美日韩成人综合| 国产小视频在线观看免费| 久久香蕉av| 中文字幕欧美亚洲| 欧美日韩精品不卡| 99日韩精品| 欧美久久在线| 午夜亚洲一区| 亚洲福利在线视频| 91精品国产自产| 美女在线视频一区| 久久中文免费视频| 精品网站999www| 国产小视频免费在线观看| 中文字幕在线导航| 国产欧美第一页| 日韩免费看网站| 国产 欧美 日韩 在线| 日韩欧美在线影院| 国产视频不卡| 日韩精品资源二区在线| 日韩精品视频免费播放| 久久69成人| 91精品国产综合久久久蜜臀粉嫩| 伊人永久在线| 国产三级视频在线| 欧美中文字幕在线观看视频| 日韩不卡在线观看| 首页国产欧美久久| 蜜桃视频中文字幕| 欧美日韩三级在线| 成人禁用看黄a在线| 亚洲欧洲一区二区天堂久久| a级在线免费观看| 久久精品国产视频| 日韩在线视频观看| 欧美日韩精品综合在线 | 91久久久久| 国产一卡2卡3卡四卡网站| 日韩欧美亚洲日产国| 日韩欧美国产免费| 日韩av综合在线观看| 在线不卡日本| 亚洲综合在线中文字幕| 久久福利视频一区二区| 欧美日韩在线播放一区| 精品久久久网| 精品三级av| 国产视频一区二| 精品国产1区二区| 亚洲大片精品永久免费| 国产999精品在线观看| 欧美黄页在线免费观看| 玖玖在线免费视频| 日韩精品在线观看视频| 国产一区在线精品| 欧美精选午夜久久久乱码6080| 亚洲高清中文字幕| 久久久91精品| 国产最顶级的黄色片在线免费观看| 国产免费久久久| 日韩视频在线一区二区三区| 国产成人精品三级| 交视频在线观看国产| 99久久婷婷| 欧美国产综合在线V| 久久中文免费视频| 精品国产1区2区3区| 欧美国产亚洲一区| 欧美特黄一区| 国产不卡在线观看视频| 中文字幕在线看视频国产欧美| 日韩欧美亚洲区| 亚洲男女av一区二区| 韩国v欧美v日本v亚洲| 日韩视频中文| 日韩 欧美 综合| 欧美日韩中文字幕在线| 国产视频1区| 极品久久久久久| 九一久久久久久| 97最新国自产拍视频在线完整在线看| 日韩欧美中文第一页| 中文字幕伊人| 亚洲理论中文字幕| 欧美不卡视频一区发布|