C#反射方法扩展

反射是程序猿的好帮手,有了反射你可以少写一半的代码。下面是一些常用的反射扩展方法。

源代码:

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; }
        }
    }
}
View Code

 

如有高见,欢迎交流与分享:)

posted @ 2017-10-17 17:29  银冰雪千载  阅读(831)  评论(2编辑  收藏  举报