反射是程序猿的好帮手,有了反射你可以少写一半的代码。下面是一些常用的反射扩展方法。
源代码:
using System; using System.Collections.Generic; using System.Linq; using System.Reflection; using System.Text; using System.Threading.Tasks; namespace LiLi.Util { public static class ReflectionExtension { public static IEnumerable<string> Keys(this Type type, BindingFlags? propBindingAttr = null, BindingFlags? fieldBindingAttr = null) { List<string> result = new List<string>(); result.AddRange(PropertyKeys(type, propBindingAttr)); result.AddRange(FieldKeys(type, fieldBindingAttr)); return result; } public static IEnumerable<string> PropertyKeys(this Type type, BindingFlags? bindingAttr = null) { PropertyInfo[] props = bindingAttr.HasValue ? type.GetProperties(bindingAttr.Value) : type.GetProperties(); return props.Select(x => x.Name); } public static IEnumerable<string> FieldKeys(this Type type, BindingFlags? bindingAttr = null) { FieldInfo[] fields = bindingAttr.HasValue ? type.GetFields(bindingAttr.Value) : type.GetFields(); return fields.Select(x => x.Name); } public static IDictionary<string, object> KeyValueList(this Type type, object obj, BindingFlags? propBindingAttr = null, BindingFlags? fieldBindingAttr = null) { Dictionary<string, object> result = new Dictionary<string, object>(); PropertyInfo[] props = propBindingAttr.HasValue ? type.GetProperties(propBindingAttr.Value) : type.GetProperties(); Array.ForEach(props, x => result.Add(x.Name, x.GetValue(obj))); FieldInfo[] fields = fieldBindingAttr.HasValue ? type.GetFields(fieldBindingAttr.Value) : type.GetFields(); Array.ForEach(fields, x => result.Add(x.Name, x.GetValue(obj))); return result; } public static IDictionary<string, object> PropertyKeyValueList(this Type type, object obj, BindingFlags? bindingAttr = null) { Dictionary<string, object> result = new Dictionary<string, object>(); PropertyInfo[] props = bindingAttr.HasValue ? type.GetProperties(bindingAttr.Value) : type.GetProperties(); Array.ForEach(props, x => result.Add(x.Name, x.GetValue(obj))); return result; } public static IDictionary<string, object> FieldKeyValueList(this Type type, object obj, BindingFlags? bindingAttr = null) { Dictionary<string, object> result = new Dictionary<string, object>(); FieldInfo[] fields = bindingAttr.HasValue ? type.GetFields(bindingAttr.Value) : type.GetFields(); Array.ForEach(fields, x => result.Add(x.Name, x.GetValue(obj))); return result; } public static bool HasKey(this Type type, string key, BindingFlags? propBindingAttr = null, BindingFlags? fieldBindingAttr = null) { return type.Keys(propBindingAttr, fieldBindingAttr).Contains(key); } public static object GetValue(this Type type, string key, object obj, BindingFlags? propBindingAttr = null, BindingFlags? fieldBindingAttr = null) { IDictionary<string, object> propertyKeyValueList = PropertyKeyValueList(type, obj, propBindingAttr); if (propertyKeyValueList.ContainsKey(key)) { return propertyKeyValueList[key]; } IDictionary<string, object> fieldKeyValueList = FieldKeyValueList(type, obj, fieldBindingAttr); if (fieldKeyValueList.ContainsKey(key)) { return fieldKeyValueList[key]; } return null; } } }
测试代码(包含使用示例) :
using System; using Microsoft.VisualStudio.TestTools.UnitTesting; using LiLi.Util; using System.Collections.Generic; using System.Linq; namespace LiLi.Util.Test { [TestClass] public class ReflectionExtensionTest { [TestMethod] public void TestKeys() { IEnumerable<string> keys = typeof(Monkey).Keys(); Assert.IsTrue(keys.SequenceEqual(new List<string> { "MonkeyIsGood", "Name", "LikeFoods", "Age" })); } [TestMethod] public void TestPropertyKeys() { IEnumerable<string> keys = typeof(Monkey).PropertyKeys(); Assert.IsTrue(keys.SequenceEqual(new List<string> { "MonkeyIsGood", "Name", "LikeFoods"})); } [TestMethod] public void TestFieldKeys() { IEnumerable<string> keys = typeof(Monkey).FieldKeys(); Assert.IsTrue(keys.SequenceEqual(new List<string> { "Age" })); } [TestMethod] public void TestKeyValueList() { IDictionary<string, object> keyValueList = typeof(Monkey).KeyValueList(new Monkey { Name = "monkey", Age = 3, LikeFoods = new string[] { "banana" }, MonkeyIsGood = false }); Assert.AreEqual("monkey", keyValueList["Name"]); Assert.AreEqual(3, keyValueList["Age"]); Assert.AreEqual("banana", (keyValueList["LikeFoods"] as string[])[0]); Assert.AreEqual(false, keyValueList["MonkeyIsGood"]); } [TestMethod] public void TestPropertyKeyValueList() { IDictionary<string, object> keyValueList = typeof(Monkey).PropertyKeyValueList(new Monkey { Name = "monkey", Age = 3, LikeFoods = new string[] { "banana" }, MonkeyIsGood = false }); Assert.AreEqual("monkey", keyValueList["Name"]); Assert.AreEqual("banana", (keyValueList["LikeFoods"] as string[])[0]); Assert.AreEqual(false, keyValueList["MonkeyIsGood"]); } [TestMethod] public void TestFieldKeyValueList() { IDictionary<string, object> keyValueList = typeof(Monkey).FieldKeyValueList(new Monkey { Name = "monkey", Age = 3, LikeFoods = new string[] { "banana" }, MonkeyIsGood = false }); Assert.AreEqual(3, keyValueList["Age"]); } [TestMethod] public void TestHasKey() { Assert.IsTrue(typeof(Monkey).HasKey("MonkeyIsGood")); Assert.IsFalse(typeof(Monkey).HasKey("MonkeyIsBad")); } [TestMethod] public void TestGetValue() { Monkey monkey = new Monkey { Name = "monkey", Age = 3, LikeFoods = new string[] { "banana" }, MonkeyIsGood = false }; Assert.AreEqual("monkey", typeof(Monkey).GetValue("Name", monkey)); Assert.AreEqual(3, typeof(Monkey).GetValue("Age", monkey)); Assert.AreEqual("banana", (typeof(Monkey).GetValue("LikeFoods", monkey) as string[])[0]); Assert.AreEqual(false, typeof(Monkey).GetValue("MonkeyIsGood", monkey)); } private class Animal { public string Name { get; set; } public string[] LikeFoods { get; set; } public int Age; private string Mystery { get; set; } } private class Monkey : Animal { public bool MonkeyIsGood { get; set; } } } }
如有高见,欢迎交流与分享:)