一起谈.NET技术,LINQ TO Reflection

简介:   引言  我们平时开发中不可避免,或者说,经常性的使用反射。但是却没有一个合适的类库帮助我们更好的利用反射。从早期的FastInvoker,到老赵的 fastreflectionlib ,无一不是在强调Fast。

  引言

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

  .Metadata()

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

        public static Metadata Metadata(this object instance)
{
return MetadataCache.Create(instance);
}

     先定义一个MockObject

        class MockAttribute : Attribute
{
public MockAttribute(string name)
{
this.Name = name;
}
public string Name
{
get;set;
}
}

class MockObject
{
public string Country = "China";

[Mock("this is the name")]
public string Name
{
get;set;
}
public string Blog
{
get;set;
}
[Mock("this is the location")]
public string Location
{
get;set;
}
public string SayHello(string name)
{
return "Hi," + name;
}
}
}

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

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

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

        using Sparrow.Reflection;
[TestMethod]
public void get_field_value()
{
var obj = new MockObject();

var field = obj.Metadata().Fields.Where(i => i.Name == "Country").FirstOrDefault();

Assert.AreEqual("China", field.GetValue(obj));
}

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

        using Sparrow.Reflection;
[TestMethod]
public void get_custom_attribute_data()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "XiaMen" };


var attribute = obj.Metadata().Properties
.Where(i => i.Name == "Name")
.SelectMany(i => i.Attributes)
.Select(i=>i.Attribute)
.OfType<MockAttribute>()
.FirstOrDefault();

Assert.AreEqual("this is the name", attribute.Name);
}

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

        using Sparrow.Reflection;
[TestMethod]
public void invoke_method()
{
var obj = new MockObject();

var method = obj.Metadata().Methods.Where(i => i.Name == "SayHello").FirstOrDefault();

Assert.AreEqual("Hi,world",method.Invoke(obj,new []{"world"}));
}

  .Proxy()

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

        public static Proxy Proxy(this object instance)
{
return new Proxy(instance);
}

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

        using Sparrow.Reflection;
[TestMethod]
public void get_value_via_property_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

Assert.AreEqual(obj.Name, obj.Proxy().Properties["Name"]);
}

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

        using Sparrow.Reflection;
[TestMethod]
public void set_value_via_property_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

var changedLocation = "Xiamen,China";
obj.Proxy().Properties["Location"] = changedLocation;

Assert.AreEqual(changedLocation,obj.Location);
}
 
 

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

        using Sparrow.Reflection;
[TestMethod]
public void get_value_via_field_proxy()
{
var obj = new MockObject { Name = "dayi", Blog = "http://walkingboy.cnblogs.com", Location = "Xiamen" };

Assert.AreEqual(obj.Country, obj.Proxy().Fields["Country"]);
}

  4.如何调用一个方法

        using Sparrow.Reflection;
[TestMethod]
public void invoke_method_via_method_proxy()
{
var obj = new MockObject();

Assert.AreEqual("Hi,world", obj.Proxy().Methods["SayHello"](new []{"world"}));
}

  .Proxy() Vs Dynamic

  我们知道在C# 4中引入了关键字Dynamic,使得 Duck Typing (DynamicDuck: Duck Typing in a Dynamic World) 成为一种可能。 查看如下代码

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

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

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

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

  不仅支持Duck Typing,同时也支持属性名称的动态化,是不是很有脚本(javascript…)的感觉呢?

  代码下载http://sparrow.codeplex.com/releases/view/50364

  详细文档http://sparrow.codeplex.com/wikipage?title=LINQ-To-Reflection

目录
相关文章
|
4月前
|
SQL 开发框架 .NET
|
4月前
|
XML SQL 开发框架
|
1月前
|
开发框架 安全 .NET
C# .NET面试系列三:集合、异常、泛型、LINQ、委托、EF!
<h2>集合、异常、泛型、LINQ、委托、EF! #### 1. IList 接口与 List 的区别是什么? IList 接口和 List 类是C#中集合的两个相关但不同的概念。下面是它们的主要区别: <b>IList 接口</b> IList 接口是C#中定义的一个泛型接口,位于 System.Collections 命名空间。它派生自 ICollection 接口,定义了一个可以通过索引访问的有序集合。 ```c# IList 接口包含一系列索引化的属性和方法,允许按索引访问、插入、移除元素等。 由于是接口,它只定义了成员的契约,而不提供具体的实现。类似于 IEnumera
149 2
|
4月前
|
开发框架 .NET
|
4月前
|
开发框架 .NET C#
|
12月前
|
缓存 前端开发 JavaScript
采用.Net Core技术框架开发的医院云LIS平台源码,B/S架构
基于B/S架构的医学实验室检验系统源码,整个系统的运行基于WEB层面,只需要在对应的工作台安装一个浏览器软件有外网即可访问。全套系统采用云部署模式,部署一套可支持多家医院检验科共同使用。 采用.Net Core新的技术框架、DEV报表、前端js封装、分布式文件存储、分布式缓存等,支持LIS独立部署,Docker部署等多种方式。
|
SQL 开发框架 JSON
【.NET基础】Linq常用语法代码演示
前言:前言不重要,linq入门常用的语法,linq语法可以用来写操作集合、数据库表集合等等几乎所有集合类型的操作。下面就写几个案例(以List集合来做的),看代码和运行结果即可。
101 0
【.NET基础】Linq常用语法代码演示
|
安全 NoSQL MongoDB
.Net线程同步技术解读
C#开发者(面试者)都会遇到lock(Monitor),Mutex,Semaphore,SemaphoreSlim这四个与锁相关的C#类型,本文期望以最简洁明了的方式阐述四种对象的区别。
.Net线程同步技术解读
|
移动开发 负载均衡 前端开发
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
143 0
2022届软件技术专业毕业生就业岗位分析(.Net方向)(7)
|
网络架构
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)
162 0
2022届软件技术专业毕业生就业岗位分析(.Net方向)(6)