Expression 獲取,設置屬性的值

有時候,業務需求,需要根據屬性名稱設置屬性的值或者根據屬性名稱獲取屬性的值,原生的反射實現比較簡單,我想用Expression Tree來實現,寫成拓展方法,現在把它記錄下來,下次直接用。

    /// <summary>
    /// Object拓展方法,.Net4.0以上
    /// </summary>
    public static class ObjectExtension
    {
        /// <summary>
        /// 根據屬性名獲取屬性值
        /// </summary>
        /// <typeparam name="T">對象類型</typeparam>
        /// <param name="t">對象</param>
        /// <param name="name">屬性名</param>
        /// <returns>屬性的值</returns>
        public static object GetPropertyValue<T>(this T t, string name)
        {
            Type type = t.GetType();
            PropertyInfo p = type.GetProperty(name);
            if (p == null)
            {
                throw new Exception(String.Format("該類型沒有名爲{0}的屬性", name));
            }
            var param_obj = Expression.Parameter(typeof(T));
            var param_val = Expression.Parameter(typeof(object));

            //轉成真實類型,防止Dynamic類型轉換成object
            var body_obj = Expression.Convert(param_obj, type);

            var body = Expression.Property(body_obj, p);
            var getValue = Expression.Lambda<Func<T, object>>(body, param_obj).Compile();
            return getValue(t);
        }

        /// <summary>
        /// 根據屬性名稱設置屬性的值
        /// </summary>
        /// <typeparam name="T">對象類型</typeparam>
        /// <param name="t">對象</param>
        /// <param name="name">屬性名</param>
        /// <param name="value">屬性的值</param>
        public static void SetPropertyValue<T>(this T t, string name, object value)
        {
            Type type = t.GetType();
            PropertyInfo p = type.GetProperty(name);
            if (p == null)
            {
                throw new Exception(String.Format("該類型沒有名爲{0}的屬性", name));
            }
            var param_obj = Expression.Parameter(type);
            var param_val = Expression.Parameter(typeof(object));
            var body_obj = Expression.Convert(param_obj, type);
            var body_val = Expression.Convert(param_val, p.PropertyType);

            //獲取設置屬性的值的方法
            var setMethod = p.GetSetMethod(true);

            //如果只是只讀,則setMethod==null
            if(setMethod!=null)
            {
                var body = Expression.Call(param_obj, p.GetSetMethod(), body_val);
                var setValue = Expression.Lambda<Action<T, object>>(body, param_obj, param_val).Compile();
                setValue(t, value);
            } 
        }
    }


測試例子

    public class Person
    {
        public string Name { set; get; }
    }

    class Program
    {

        static void Main(string[] args)
        {
            var person = new Person()
            {
                Name = "123"
            };

            dynamic p = new { Name = "123" };
            object op = (object)p;

            Console.WriteLine("Person 的Name屬性的值是{0}",person.GetPropertyValue("Name"));
            person.SetPropertyValue("Name", "456");
            Console.WriteLine("Person 的Name屬性的值修改後是{0}", person.Name);
            Console.WriteLine("dynamic 的Name屬性的值是{0}", op.GetPropertyValue("Name"));
            op.SetPropertyValue("Name", 456);
            Console.WriteLine("dynamic 的Name屬性的值修改後是{0}", op.GetPropertyValue("Name"));
        }
    }


測試結果

Person 的Name屬性的值是123
Person 的Name屬性的值修改後是456
dynamic 的Name屬性的值是123
dynamic 的Name屬性的值修改後是123
請按任意鍵繼續. . .

發佈了83 篇原創文章 · 獲贊 12 · 訪問量 18萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章