详解LINQtoReflection反射机制

引言

成都创新互联专注于咸阳企业网站建设,响应式网站设计,电子商务商城网站建设。咸阳网站建设公司,为咸阳等地区提供建站服务。全流程定制网站设计,专业设计,全程项目跟踪,成都创新互联专业和态度为您提供的服务

我们平时开发中不可避免,或者说,经常性的使用反射。但是却没有一个合适的类库帮助我们更好的利用反射。从早期的FastInvoker,到老赵的 fastreflectionlib ,无一不是在强调Fast。这是因为反射的性能损耗比较厉害,所以大家都集中精力解决性能的问题,但是在易用性方面却鲜有改进。今天我为大家带来一个即兼顾性能又具有良好的使用体验的反射类库.

.Metadata()

此类库以LINQ TO Object为基础,可以通过调用.Metadata()方法获取对应Type的完整Metadata信息。此信息会被进行缓存,并且使用fastreflectionlib的核心Lambda代码,利用DynamicMethod代替直接的反射执行。

 
 
 
  1. public static Metadata Metadata(this object instance)         
  2.  {             
  3.  return MetadataCache.Create(instance);      
  4.     }      

先定义一个MockObject

 
 
 
  1. class MockAttribute : Attribute        
  2.   {              
  3. public MockAttribute(string name)            {                 
  4.  this.Name = name;         
  5.      }          
  6.     public string Name        
  7.       {                get;set;          
  8.     }        }       
  9.    class MockObject       
  10.    {          
  11.     public string Country = "China";                   
  12.        [Mock("this is the name")]      
  13.         public string Name      
  14.         {                get;set;            }         
  15.      public string Blog        
  16.       {                get;set;     
  17.          }            
  18.   [Mock("this is the location")]        
  19.       public string Location     
  20.          {                get;set;            }            
  21.   public string SayHello(string name)            {              
  22.     return "Hi," + name;        
  23.       }        }    } 

1.如何获取一个属性,并进行取值、赋值?

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void set_property_value()         
  4.  {              
  5. var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "XiaMen" };              
  6. var property = obj.Metadata().Properties.Where(i => i.Name == "Location").FirstOrDefault();             
  7.  var changedLocation = "Xiamen,China";             
  8.  //get value  
  9.  //var value = property.GetValue(obj);  
  10. property.SetValue(obj, changedLocation);  
  11. Assert.AreEqual(changedLocation, obj.Location);  
  12.         }    

2.如果获取一个字段的值?

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void get_field_value()         
  4.  {              
  5. var obj = new MockObject();              
  6. var field = obj.Metadata().Fields.Where(i => i.Name == "Country").FirstOrDefault();  
  7. Assert.AreEqual("China", field.GetValue(obj));         
  8.  }    

3.如何获取一个自定义CustomAttribute?

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void get_custom_attribute_data()        {              
  4. var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "XiaMen" };             
  5.  var attribute = obj.Metadata().Properties                 
  6.  .Where(i => i.Name == "Name")                 
  7.  .SelectMany(i => i.Attributes)                 
  8.  .Select(i=>i.Attribute)                  
  9. .OfType()                  
  10. .FirstOrDefault();              
  11. Assert.AreEqual("this is the name", attribute.Name);        
  12.   }   

4.如何调用一个指定名称的Method?

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void invoke_method()       
  4.    {              
  5. var obj = new MockObject();              
  6. var method = obj.Metadata().Methods.Where(i => i.Name == "SayHello").FirstOrDefault();  
  7. Assert.AreEqual("Hi,world",method.Invoke(obj,new []{"world"}));       
  8.    }.Proxy() 

对于某些应用场景来说,使用LINQ To Object去查询并获取单一的方法、属性,字段,总觉得还是要写非常多的代码。要先.Metadata(), 接下来.Where(), 虽然代码很优雅,但是还是有很多工作要做。所以这里也提供一个针对获取单一方法、属性、字段的替代写法。

 
 
 
  1. public static Proxy Proxy(this object instance)  
  2.         {  
  3.             return new Proxy(instance);  
  4.         } 

1.如何获取一个属性的值

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void get_value_via_property_proxy()        {             
  4.  var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };             
  5.  Assert.AreEqual(obj.Name, obj.Proxy().Properties["Name"]);   
  6.        } 

2.如何设置一个属性的值

 
 
 
  1. using Sparrow.Reflection;     
  2.      [TestMethod]       
  3.    public void set_value_via_property_proxy()        {            
  4.   var obj = new MockObject 
  5. { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };           
  6.    var changedLocation = "Xiamen,China";      
  7.       obj.Proxy().Properties["Location"] = changedLocation;       
  8.        Assert.AreEqual(changedLocation,obj.Location);      
  9.     }  

3.如何获取一个字段的值

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void get_value_via_field_proxy()        {             
  4.  var obj = new MockObject 
  5. { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };              
  6. Assert.AreEqual(obj.Country, obj.Proxy().Fields["Country"]);      
  7.     } 

4.如何调用一个方法

 
 
 
  1. using Sparrow.Reflection;          
  2. [TestMethod]          
  3. public void invoke_method_via_method_proxy()        {              
  4. var obj = new MockObject();            
  5. Assert.AreEqual("Hi,world", obj.Proxy().Methods["SayHello"](new []{"world"}));       
  6.    }.Proxy() Vs Dynamic 

我们知道在C# 4中引入了关键字Dynamic,使得 Duck Typing (DynamicDuck: Duck Typing in a Dynamic World)

成为一种可能。 查看如下代码

 
 
 
  1. public void Run(dynamic obj)       
  2.    {              Console.WriteLine(obj.Name);  
  3.         }  

这个代码并没有指定参数obj的类型,obj的类型是由运行时候传入的真实值决定,只要该类型包含一个Name的属性就可以了。

但是仅仅支持Duck Typing就够了嘛? 似乎不够动态哦。这边的.Name 是在编译时(或者说编码时)就确定,但是往往我们的使用场景中,连这个也都是动态,比如是接受自Form,或者来自配置信息,这个时候dynamic就无能为力了。

反过来看看使用.Proxy()的情况

 
 
 
  1. public void Run(object obj,string propertyName)       {           
  2.    Console.WriteLine(obj.Proxy().Properties[propertyName])     
  3.     } 

当前标题:详解LINQtoReflection反射机制
当前链接:http://www.36103.cn/qtweb/news23/21273.html

网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

广告

声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联