代码改变世界

C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到

2012-06-29 00:27  音乐让我说  阅读(2511)  评论(0编辑  收藏  举报

可能你还感兴趣:

1. C# Lambda 表达式学习之(一):得到一个类的字段(Field)或属性(Property)名,强类型得到

2. C# Lambda 表达式学习之(二):LambdaExpression 实战练习

3. 基于 Entity Framework FluentAPI 思想的强类型的 Lambda Expressions 实体映射

4. C# Lambda 表达式学习之(三):动态构建类似于 c => c.Age == null || c.Age > 18 的表达式 

5. C# Lambda 表达式学习之(四):动态构建类似于 c => c.Age == 2 || c.Age == 5 || c => c.Age == 17 等等一个或多个 OrElse 的表达式

 

简单属性

所谓“简单属性”,是指一个类的属性的类型是基本数据类型(int、string、guid、datetime、float、decimal 等等)。

直接贴代码了:

using System;
using System.Text;
using System.Linq;
using System.Linq.Expressions;
using System.Collections.Generic;


namespace DearBruce.ConAppTest
{
    class Program
    {
        static void Main(string[] args)
        {
            string idStr = ExpressionHelper<UserInfo>.GetPropertyName(u => u.Id);
            Console.WriteLine(idStr); // 打印:"Id"
            string nameStr = ExpressionHelper<UserInfo>.GetPropertyName(u => u.Name);
            Console.WriteLine(nameStr); // 打印:"Name"
            Console.Read();
        }
    }

    public class ExpressionHelper<T> where T : class, new()
    {
        /// <summary>
        /// 得到一个字段(Field)或属性(Property)名
        /// </summary>
        /// <typeparam name="TProperty"></typeparam>
        /// <param name="express"></param>
        /// <returns></returns>
        public static string GetPropertyName<TProperty>(Expression<Func<T, TProperty>> express)
        {
            if (express == null)
            {
                throw new ArgumentNullException("express");
            }
            MemberExpression memberExpression = express.Body as MemberExpression;
            if (memberExpression == null)
            {
                throw new ArgumentException("请为类型 \"" + typeof(T).FullName + "\" 的指定一个字段(Field)或属性(Property)作为 Lambda 的主体(Body)。");
            }
            return memberExpression.Member.Name;
        }
    }

    class UserInfo
    {
        public int Id { get; set; }

        public string Name { get; set; }

        public DateTime DateOfBirth { get; set; }
    }
}

 我们换另一种方式

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Linq.Expressions;
using System.Reflection;

namespace MyApp.TestMvc.ConApp
{
    class Program
    {
        static void Main(string[] args)
        {
            object obj = +5;
            Console.WriteLine(obj); // 打印 5

            Product p = new Product();
            
            string value1 = ExpressionHelper.GetPropertyName(() => p.ProductName);
            Console.WriteLine("value1:" + value1); // ProductName

            string value2 = ExpressionHelper.GetPropertyName<Product>(c => +c.Category_CategoryId.Id);
            Console.WriteLine("value2:" + value2); // Id

            p.ProductName = "我爱编程";

            string tempPopName;
            object value3 = ExpressionHelper.GetPropertyNameAndValue(() => p.ProductName, out tempPopName);
            Console.WriteLine("value3:" + value3 + ", popName:" + tempPopName); // 我爱编程, ProductName
        }
    }

    public class Category
    {
        public int Id { get; set; }

        public string CateName { get; set; }
    }

    public class Product
    {
        public int Id { get; set; }

        public string ProductName { get; set; }

        public int CategoryId { get; set; }

        public Category Category_CategoryId { get; set; }
    }

    public class ExpressionHelper
    {
        public static string GetPropertyName(Expression<Func<object>> exp)
        {
            MemberExpression body = exp.Body as MemberExpression;
            if (body == null)
            {
                throw new InvalidOperationException("Not a member access.");
            }
            PropertyInfo member = body.Member as PropertyInfo;
            return member.Name;
        }

        public static string GetPropertyName<T>(Expression<Func<T, object>> exp)
        {
            MemberExpression body = null;
            if (exp.Body is MemberExpression)
            {
                body = exp.Body as MemberExpression;
            }
            if (exp.Body is UnaryExpression)
            {
                UnaryExpression expression2 = exp.Body as UnaryExpression;
                if (expression2.Operand is MemberExpression)
                {
                    body = expression2.Operand as MemberExpression;
                }
            }
            if (body == null)
            {
                throw new InvalidOperationException("Not a member access.");
            }
            PropertyInfo member = body.Member as PropertyInfo;
            return member.Name;
        }

        public static object GetPropertyNameAndValue(Expression<Func<object>> exp, out string propName)
        {
            MemberExpression body = exp.Body as MemberExpression;
            PropertyInfo member = null;
            if (exp.Body is MemberExpression)
            {
                member = ((MemberExpression)exp.Body).Member as PropertyInfo;
            }
            else if (exp.Body is UnaryExpression)
            {
                member = ((MemberExpression)((UnaryExpression)exp.Body).Operand).Member as PropertyInfo;
            }
            object obj2 = exp.Compile().DynamicInvoke(new object[0]);
            propName = member.Name;
            return obj2;
        }
    }
}

 完毕!

复杂属性

所谓“复杂属性”,是指一个类的属性的类型是非基本数据类型,一般指类、嵌套类、接口等等。

下面的代码来自 https://github.com/MarlabsInc/SocialGoal

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Linq.Expressions;

namespace SocialGoal.Web.Core
{
    public static class HtmlExtensions
    {
        public static MvcHtmlString File(this HtmlHelper html, string name)
        {
            var tb = new TagBuilder("input");
            tb.Attributes.Add("type", "file");
            tb.Attributes.Add("name", name);
            tb.GenerateId(name);
            return MvcHtmlString.Create(tb.ToString(TagRenderMode.SelfClosing));
        }


        public static MvcHtmlString FileFor<TModel, TProperty>(this HtmlHelper<TModel> html, Expression<Func<TModel, TProperty>> expression)
        {
            string name = GetFullPropertyName(expression);
            return html.File(name);
        }

        #region Helpers

        static string GetFullPropertyName<T, TProperty>(Expression<Func<T, TProperty>> exp)
        {
            MemberExpression memberExp;

            if (!TryFindMemberExpression(exp.Body, out memberExp))
                return string.Empty;

            var memberNames = new Stack<string>();

            do
            {
                memberNames.Push(memberExp.Member.Name);
            }
            while (TryFindMemberExpression(memberExp.Expression, out memberExp));

            return string.Join(".", memberNames.ToArray());
        }

        static bool TryFindMemberExpression(Expression exp, out MemberExpression memberExp)
        {
            memberExp = exp as MemberExpression;

            if (memberExp != null)
                return true;

            if (IsConversion(exp) && exp is UnaryExpression)
            {
                memberExp = ((UnaryExpression)exp).Operand as MemberExpression;

                if (memberExp != null)
                    return true;
            }

            return false;
        }

        static bool IsConversion(Expression exp)
        {
            return (exp.NodeType == ExpressionType.Convert || exp.NodeType == ExpressionType.ConvertChecked);
        }

        #endregion
    }
}

 

谢谢浏览!