采用Delegate对一个未知类型的对象进行"遍历"
来源:互联网 发布:好看的末世小说知乎 编辑:程序博客网 时间:2024/05/01 14:58
文章阅读顺序建议:
本系列有一个递进的顺序,可依次阅读以下的文章:
一、采用Delegate对一个未知类型的对象进行"遍历"
http://blog.csdn.net/kmguo/article/details/17392185
二、采用表达式树(Expression Tree)对一个对象的属性进行“遍历”
http://blog.csdn.net/kmguo/article/details/19975331
三、 采用表达式树(Expression Block)对一个对象的属性进行“遍历”
http://blog.csdn.net/kmguo/article/details/20376187
由于有时候需要对一个不知类型的object进行“遍历”,得到它的所有公有的属性和字段。虽然可以采用反射来实现,但是代价太高了,特别是要多次执行时。因此,我写了一个用Delegate来实现的方法,供大家参考和交流。
我定义了MemberAccessor.dll。里面有四个文件,具体的内容如下:
定义一个获得对象的某个Member的Value的接口:IMemberAccessor.cs
namespace MemberAccessor{ /// <summary> /// 获得Member值的接口 /// </summary> public interface IMemberAccessor { object GetValue(object instance); }}
定义一个获取指定类型的指定属性的GetValue的类: PropertyDelegateAccessor.cs
using System;using System.Reflection;namespace MemberAccessor{ /// <summary> /// 针对PropertyInfo,生成一个能够获得PropertyInfo Value的实例 /// </summary> /// <typeparam name="TType"></typeparam> /// <typeparam name="TMember"></typeparam> public class PropertyDelegateAccesstor<TType, TMember> : IMemberAccessor { private Func<TType, TMember> m_getValueDelegate; public PropertyDelegateAccesstor(Type type, MethodInfo methodInfo) { m_getValueDelegate = (Func<TType, TMember>) Delegate.CreateDelegate(typeof (Func<TType, TMember>), null, methodInfo); } public object GetValue(object instance) { return m_getValueDelegate((TType)instance); } }}
定义一个获取指定类型的指定字段的GetValue的类:FieldDelegateAccessor
using System;using System.Reflection;namespace MemberAccessor{ /// <summary> /// 提交一个FieldInfo,生成一个获得该FieldInfo Value的实例 /// </summary> public class FieldDelegateAccessor:IMemberAccessor { private Func<object, object> m_getValueDelegate; public FieldDelegateAccessor(FieldInfo fieldInfo) { m_getValueDelegate = fieldInfo.GetValue; } public object GetValue(object instance) { return m_getValueDelegate(instance); } }}
利用上面的三个接口与类,生成一个针对指定类型的所有属性与字段访问的类:InstanceDelegateAccessor.cs
using System;using System.Collections.Generic;using System.Reflection;namespace MemberAccessor{ /// <summary> /// 针对某一个类型的实例,生成一个获得该类型的相应Property与Field 值的实例 /// </summary> public class InstanceDelegateAccessor { private Dictionary<string, IMemberAccessor> m_memberAccessors; public InstanceDelegateAccessor(Type type, BindingFlags propertyBindingFlags, BindingFlags fieldBindingFlags) { m_memberAccessors = new Dictionary<string, IMemberAccessor>(); #region create accessor //property var pis = type.GetProperties(propertyBindingFlags); foreach (var pi in pis) { var name = pi.Name; var accessor = Activator.CreateInstance( typeof (PropertyDelegateAccesstor<,>).MakeGenericType(type, pi.PropertyType), type, pi.GetGetMethod()) as IMemberAccessor; m_memberAccessors.Add(name, accessor); } //field var fis = type.GetFields(fieldBindingFlags); foreach (var fi in fis) { var name = fi.Name; var accessor = new FieldDelegateAccessor(fi); m_memberAccessors.Add(name, accessor); } #endregion } public object GetValue(object instance, string memberName) { if (instance == null || string.IsNullOrWhiteSpace(memberName)) { throw new ArgumentNullException("input paremeters have null value."); } IMemberAccessor accessor = null; if (m_memberAccessors.TryGetValue(memberName, out accessor) == false || accessor == null) { throw new ArgumentException("can not find any MemberDelegate for memberName:" + memberName); } return accessor.GetValue(instance); } } /// <summary> /// 返回一个类的所有字段,属性的序列对: /// Prop: Value /// Field: Value /// </summary> /// <param name="instance"></param> /// <returns></returns> public IList<Tuple<object,object>> GetValues(object instance) { var objs = new List<Tuple<object, object>>(); foreach (var key in m_memberAccessors.Keys) { var value = GetValue(instance, key); objs.Add(new Tuple<object, object>(key, value)); } return objs; }}
最后,测试:
说明:
在Main方法里先创建两个对象,一个是StringTest,另一个是IntTest。并创建与它们类型相对应的InstanceDelegateAccessor对象。
最后分别调用ShowAllPublicValue,将对象和它对应的InstanceDelegateAccessor对象作为参数传入,再在该方法里打印对应的属性与字段。
using System;using System.Reflection;using MemberAccessor;namespace Study{ public class Test { public string stringField; public int IntProperty { get; set; } public Test(int prop ) { stringField = "stringField value"; IntProperty = prop; } } public class Program { public static void Main(string[] args) { InstanceDelegateAccessor ida = null; int total = 10; //多个相同的类,采用同一个Serializer即可 for (int i = 0; i < total; ++i) { //新建的Object Test test = new Test(i); if (ida == null) { //没有Serializer,新建 ida = new InstanceDelegateAccessor(test.GetType(), BindingFlags.Public | BindingFlags.Instance, BindingFlags.Instance | BindingFlags.Public); } //返回的结果: var results = ida.GetValues(test); foreach (var result in results) { Console.WriteLine(result.Item1 + ": " + result.Item2); } Console.WriteLine(); } } }}
有一点不足的是,如果一个类里引用了另一个类的对象,这样的话,就只能调用默认的ToString函数了,而不是这个对象的属性了。
比如说:
class A{
public B b;
}
class B{
public int Bid{get;set;}
}
则一旦我去获取A的所有字段,那么对于A里的b对象,我就只能得到b的ToString()方法返回的结果,我无法得到B里的属性Bid。
有知道如何获得的朋友,希望交流。
参考:http://www.cnblogs.com/nankezhishi/archive/2012/02/11/dynamicaccess.html#di
0 0
- 采用Delegate对一个未知类型的对象进行"遍历"
- 采用表达式树(Expression Tree)对一个对象的属性进行“遍历”
- 采用表达式树(Expression Block)对一个对象的属性进行“遍历”
- 采用表达式树(Expression Tree)对一个对象的属性进行“遍历”
- 采用表达式树(Expression Block)对一个对象的属性进行“遍历”
- 对一个List<B>类型的对象进行排序
- struts2对一些属性的使用和对session封装对象类型采用jstl技术的遍历(配图解)
- 模板函数中使用未知类型的容器--如何遍历一个未知容器
- 遍历一个未知的json
- 采用动态代理的方式对一个类进行增强
- 定义一个未知类型的数据
- 【java学习记录】3.采用面向对象的方法设计一个能对复数(Complex)进行加、减、乘法的简单运算的程序
- 封装一个对磁盘,文件夹,文件进行遍历的类
- 一个对磁盘,文件夹,文件进行遍历的类
- IOS 遍历未知对象的属性和方法
- IOS 遍历未知对象的属性和方法
- IOS 遍历未知对象的属性和方法
- IOS 遍历未知对象的属性和方法
- ZLIB:gzopen与compress2函数压缩的内容有什么的
- 让html select支持readonly属性
- Extjs4.0 之Ext.Class 属性详解 (alias/mixins /uses/requires/singleton等属性)
- (二)用JAVA编写MP3解码器——帧头信息解码
- Tomcat是什么?
- 采用Delegate对一个未知类型的对象进行"遍历"
- Android 自定义View(3) -- 获得Bitmap的三种方法
- mysql大数据表导入导出
- 互联网免费鸡蛋,给还是不给?要还是不要?
- iTween.cs的WP8实现
- rails twitter-bootstrap-rails
- ApplicationInfo.FLAG_PERSISTENT
- Django实践-简单实例
- (转)RelativeLayout相对布局常用属性