Util應用程式框架公共操作類(八):Lambda表示式公共操作類(二)

weixin_30639719發表於2020-04-05

  前面介紹了查詢的基礎擴充套件,下面準備給大家介紹一些有用的查詢封裝手法,比如對日期範圍查詢,數值範圍查詢的封裝等,為了支援這些功能,需要增強公共操作類。

  Lambda表示式公共操作類,我在前面已經簡單介紹過,要麼從Lambda表示式中獲取資訊,要麼動態建立Lambda表示式,本篇直接貼程式碼,如果發現有些程式碼與以前不同,原因有二,一是之前還未用到,只發了部分程式碼,二是可能程式碼已重構。需要說明的一點是,我不會考慮程式碼相容性,API命名隨時可能修改,如果你直接將本系列的程式碼用到你的專案上要格外注意。

  修改Util專案的Lambda類,程式碼如下。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using DynamicExpression = Util.Lambdas.Dynamics.DynamicExpression;

namespace Util {
    /// <summary>
    /// Lambda表示式操作
    /// </summary>
    public class Lambda {

        #region GetName(獲取成員名稱)

        /// <summary>
        /// 獲取成員名稱,範例:t => t.Name,返回 Name
        /// </summary>
        /// <param name="expression">表示式,範例:t => t.Name</param>
        public static string GetName( LambdaExpression expression ) {
            var memberExpression = GetMemberExpression( expression );
            if ( memberExpression == null )
                return string.Empty;
            string result = memberExpression.ToString();
            return result.Substring( result.IndexOf( ".", StringComparison.Ordinal ) + 1 );
        }

        /// <summary>
        /// 獲取成員表示式
        /// </summary>
        private static MemberExpression GetMemberExpression( LambdaExpression expression ) {
            if ( expression == null )
                return null;
            var unaryExpression = expression.Body as UnaryExpression;
            if ( unaryExpression == null )
                return expression.Body as MemberExpression;
            return unaryExpression.Operand as MemberExpression;
        }

        #endregion

        #region GetMember(獲取成員)

        /// <summary>
        /// 獲取成員
        /// </summary>
        /// <param name="expression">表示式,範例:t => t.Name</param>
        public static MemberInfo GetMember( LambdaExpression expression ) {
            var memberExpression = GetMemberExpression( expression );
            if ( memberExpression == null )
                return null;
            return memberExpression.Member;
        }

        #endregion

        #region GetValue(獲取值)

        /// <summary>
        /// 獲取值,範例:t => t.Name == "A",返回 A
        /// </summary>
        /// <param name="expression">表示式,範例:t => t.Name == "A"</param>
        public static object GetValue( LambdaExpression expression ) {
            if ( expression == null )
                return null;
            var memberExpression = expression.Body as MemberExpression;
            if ( memberExpression != null )
                return GetMemberValue( memberExpression );
            BinaryExpression binaryExpression = GetBinaryExpression( expression );
            if ( binaryExpression != null )
                return GetBinaryValue( binaryExpression );
            var callExpression = expression.Body as MethodCallExpression;
            if ( callExpression != null )
                return GetMethodValue( callExpression );
            return null;
        }

        /// <summary>
        /// 獲取二元表示式
        /// </summary>
        private static BinaryExpression GetBinaryExpression( LambdaExpression expression ) {
            var binaryExpression = expression.Body as BinaryExpression;
            if ( binaryExpression != null )
                return binaryExpression;
            var unaryExpression = expression.Body as UnaryExpression;
            if ( unaryExpression == null )
                return null;
            return unaryExpression.Operand as BinaryExpression;
        }

        /// <summary>
        /// 獲取二元表示式的值
        /// </summary>
        private static object GetBinaryValue( BinaryExpression binaryExpression ) {
            var unaryExpression = binaryExpression.Right as UnaryExpression;
            if ( unaryExpression != null )
                return GetConstantValue( unaryExpression.Operand );
            var memberExpression = binaryExpression.Right as MemberExpression;
            if ( memberExpression != null )
                return GetMemberValue( memberExpression );
            return GetConstantValue( binaryExpression.Right );
        }

        /// <summary>
        /// 獲取屬性表示式的值
        /// </summary>
        private static object GetMemberValue( MemberExpression expression ) {
            if ( expression == null )
                return null;
            var field = expression.Member as FieldInfo;
            if ( field != null ) {
                var constValue = GetConstantValue( expression.Expression );
                return field.GetValue( constValue );
            }
            var property = expression.Member as PropertyInfo;
            if ( property == null )
                return null;
            var value = GetMemberValue( expression.Expression as MemberExpression );
            return property.GetValue( value );
        }

        /// <summary>
        /// 獲取常量值
        /// </summary>
        private static object GetConstantValue( Expression expression ) {
            var constantExpression = expression as ConstantExpression;
            if ( constantExpression == null )
                return null;
            return constantExpression.Value;
        }

        /// <summary>
        /// 獲取方法呼叫表示式的值
        /// </summary>
        private static object GetMethodValue( MethodCallExpression callExpression ) {
            var argumentExpression = callExpression.Arguments.FirstOrDefault();
            var memberExpression = argumentExpression as MemberExpression;
            if ( memberExpression != null )
                return GetMemberValue( memberExpression );
            return GetConstantValue( argumentExpression );
        }

        #endregion

        #region GetParameter(獲取引數)

        /// <summary>
        /// 獲取引數,範例:t.Name,返回 t
        /// </summary>
        /// <param name="expression">表示式,範例:t.Name</param>
        public static ParameterExpression GetParameter( LambdaExpression expression ) {
            if ( expression == null )
                return null;
            BinaryExpression binaryExpression = GetBinaryExpression( expression );
            if ( binaryExpression == null )
                return null;
            return GetParameterByMember( binaryExpression.Left );
        }

        /// <summary>
        /// 遞迴獲取引數
        /// </summary>
        private static ParameterExpression GetParameterByMember( Expression expression ) {
            if ( expression == null )
                return null;
            ParameterExpression result = expression as ParameterExpression;
            if ( result != null )
                return result;
            MemberExpression memberExpression = expression as MemberExpression;
            if ( memberExpression == null )
                return null;
            return GetParameterByMember( memberExpression.Expression );
        }

        #endregion

        #region GetAttribute(獲取特性)

        /// <summary>
        /// 獲取特性
        /// </summary>
        /// <typeparam name="TEntity">實體型別</typeparam>
        /// <typeparam name="TProperty">屬性型別</typeparam>
        /// <typeparam name="TAttribute">特性型別</typeparam>
        /// <param name="propertyExpression">屬性表示式</param>
        public static TAttribute GetAttribute<TEntity, TProperty, TAttribute>( Expression<Func<TEntity, TProperty>> propertyExpression )
            where TAttribute : Attribute {
            var memberInfo = GetMember( propertyExpression );
            return memberInfo.GetCustomAttribute<TAttribute>();
        }

        #endregion

        #region GetAttributes(獲取特性列表)

        /// <summary>
        /// 獲取特性列表
        /// </summary>
        /// <typeparam name="TEntity">實體型別</typeparam>
        /// <typeparam name="TProperty">屬性型別</typeparam>
        /// <typeparam name="TAttribute">特性型別</typeparam>
        /// <param name="propertyExpression">屬性表示式</param>
        public static IEnumerable<TAttribute> GetAttributes<TEntity, TProperty, TAttribute>( Expression<Func<TEntity, TProperty>> propertyExpression ) where TAttribute : Attribute {
            var memberInfo = GetMember( propertyExpression );
            return memberInfo.GetCustomAttributes<TAttribute>();
        }

        #endregion

        #region Constant(獲取常量)

        /// <summary>
        /// 獲取常量表示式,自動轉換值的型別
        /// </summary>
        /// <param name="expression">表示式</param>
        /// <param name="value"></param>
        public static ConstantExpression Constant( Expression expression, object value ) {
            var memberExpression = expression as MemberExpression;
            if ( memberExpression == null )
                return Expression.Constant( value );
            return Expression.Constant( value, memberExpression.Type );
        }

        #endregion

        #region GetCriteriaCount(獲取謂詞條件的個數)

        /// <summary>
        /// 獲取謂詞條件的個數
        /// </summary>
        /// <param name="expression">謂詞表示式,範例:t => t.Name == "A"</param>
        public static int GetCriteriaCount( LambdaExpression expression ) {
            if ( expression == null )
                return 0;
            var result = expression.ToString().Replace( "AndAlso", "|" ).Replace( "OrElse", "|" );
            return result.Split( '|' ).Count();
        }

        #endregion

        #region Equal(等於表示式)

        /// <summary>
        /// 建立等於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Equal<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .Equal( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        /// <summary>
        /// 建立引數
        /// </summary>
        private static ParameterExpression CreateParameter<T>() {
            return Expression.Parameter( typeof( T ), "t" );
        }

        #endregion

        #region NotEqual(不等於表示式)

        /// <summary>
        /// 建立不等於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> NotEqual<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .NotEqual( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region Greater(大於表示式)

        /// <summary>
        /// 建立大於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Greater<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .Greater( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region Less(小於表示式)

        /// <summary>
        /// 建立小於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Less<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .Less( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region GreaterEqual(大於等於表示式)

        /// <summary>
        /// 建立大於等於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> GreaterEqual<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .GreaterEqual( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region LessEqual(小於等於表示式)

        /// <summary>
        /// 建立小於等於運算lambda表示式
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> LessEqual<T>( string propertyName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                    .LessEqual( value )
                    .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region Contains(呼叫Contains方法)

        /// <summary>
        /// 呼叫Contains方法
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Contains<T>( string propertyName, object value ) {
            return Call<T>( propertyName, "Contains", value );
        }

        /// <summary>
        /// 呼叫方法
        /// </summary>
        private static Expression<Func<T, bool>> Call<T>( string propertyName, string methodName, object value ) {
            var parameter = CreateParameter<T>();
            return parameter.Property( propertyName )
                .Call( methodName, value )
                .ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region Starts(呼叫StartsWith方法)

        /// <summary>
        /// 呼叫StartsWith方法
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Starts<T>( string propertyName, string value ) {
            var parameter = CreateParameter<T>();
            var property = parameter.Property( propertyName );
            var call = Expression.Call( property, property.Type.GetMethod( "StartsWith", new Type[] { typeof( string ) } ),
                Expression.Constant( value ) );
            return call.ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region Ends(呼叫EndsWith方法)

        /// <summary>
        /// 呼叫EndsWith方法
        /// </summary>
        /// <typeparam name="T">物件型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        public static Expression<Func<T, bool>> Ends<T>( string propertyName, string value ) {
            var parameter = CreateParameter<T>();
            var property = parameter.Property( propertyName );
            var call = Expression.Call( property, property.Type.GetMethod( "EndsWith", new Type[] { typeof( string ) } ),
                Expression.Constant( value ) );
            return call.ToLambda<Func<T, bool>>( parameter );
        }

        #endregion

        #region ParsePredicate(解析為謂詞表示式)

        /// <summary>
        /// 解析為謂詞表示式
        /// </summary>
        /// <typeparam name="T">實體型別</typeparam>
        /// <param name="propertyName">屬性名</param>
        /// <param name="value"></param>
        /// <param name="operator">運算子</param>
        public static Expression<Func<T, bool>> ParsePredicate<T>( string propertyName, object value, Operator @operator ) {
            var parameter = Expression.Parameter( typeof( T ), "t" );
            return parameter.Property( propertyName ).Operation( @operator, value ).ToLambda<Func<T, bool>>( parameter );
        }

        /// <summary>
        /// 解析為謂詞表示式
        /// </summary>
        /// <typeparam name="T">實體型別</typeparam>
        /// <param name="predicateExpression">謂詞表示式字串,引數佔位符為@0,@1,@2 ...</param>
        /// <param name="values"></param>
        public static Expression<Func<T, bool>> ParsePredicate<T>( string predicateExpression, params object[] values ) {
            return DynamicExpression.ParseLambda( typeof( T ), typeof( bool ), predicateExpression, values ) as Expression<Func<T, bool>>;
        }

        #endregion
    }
}

  在Util.Tests單元測試專案新建兩個測試樣例,程式碼如下。

using System.ComponentModel.DataAnnotations;

namespace Util.Tests.Samples {
    /// <summary>
    /// 測試1
    /// </summary>
    public class Test1 {
        [StringLength( 20, ErrorMessage = "長度不能超過20" )]
        [Required( ErrorMessage = "名稱不能為空" )]
        [Display( Name = "名稱" )]
        public string Name { get; set; }
        public int Age { get; set; }
        public int? NullableInt { get; set; }
        public decimal? NullableDecimal { get; set; }
        public TestA A { get; set; }
        public class TestA {
            public int Integer { get; set; }
            public string Address { get; set; }
            public TestB B { get; set; }
            public class TestB {
                public string Name { get; set; }
            }
        }
    }
}


using System;
using System.ComponentModel.DataAnnotations;

namespace Util.Tests.Samples {
    /// <summary>
    /// 測試2
    /// </summary>
    [Serializable]
    public class Test2 {
        public Test2() {
        }
        public Test2( string name ) {
            Name = name;
        }

        [Required(ErrorMessage = "名稱不能為空")]
        public string Name { get; set; }
        public int Int { get; set; }
        public int? NullableInt { get; set; }
        public decimal? NullableDecimal { get; set; }
        public decimal Decimal { get; set; }
        public TestA A { get; set; }
        [Serializable]
        public class TestA {
            public int Integer { get; set; }
            public string Address { get; set; }
            public TestB B { get; set; }
            public class TestB {
                public string Name { get; set; }
            }
        }
    }
}

  修改Util.Tests單元測試專案LambdaTest單元測試,程式碼如下。

using System;
using System.Collections.Generic;
using System.ComponentModel.DataAnnotations;
using System.Linq;
using System.Linq.Expressions;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Util.Tests.Samples;

namespace Util.Tests {
    /// <summary>
    /// 表示式測試
    /// </summary>
    [TestClass]
    public class LambdaTest {

        #region GetName(獲取成員名稱)

        /// <summary>
        /// 獲取成員名稱
        /// </summary>
        [TestMethod]
        public void TestGetName() {
            //空值返回空字串
            Assert.AreEqual( "", Lambda.GetName( null ) );

            //返回一級屬性名
            Expression<Func<Test1, string>> expression = test => test.Name;
            Assert.AreEqual( "Name", Lambda.GetName( expression ) );

            //返回二級屬性名
            Expression<Func<Test1, string>> expression2 = test => test.A.Address;
            Assert.AreEqual( "A.Address", Lambda.GetName( expression2 ) );

            //返回三級屬性名
            Expression<Func<Test1, string>> expression3 = test => test.A.B.Name;
            Assert.AreEqual( "A.B.Name", Lambda.GetName( expression3 ) );

            //測試可空整型
            Expression<Func<Test1, int?>> expression4 = test => test.NullableInt;
            Assert.AreEqual( "NullableInt", Lambda.GetName( expression4 ) );

            //測試型別轉換
            Expression<Func<Test1, int?>> expression5 = test => test.Age;
            Assert.AreEqual( "Age", Lambda.GetName( expression5 ) );
        }

        #endregion

        #region GetValue(獲取成員值)

        /// <summary>
        /// 獲取成員值,委託返回型別為Object
        /// </summary>
        [TestMethod]
        public void TestGetValue_Object() {
            Expression<Func<Test1, object>> expression = test => test.Name == "A";
            Assert.AreEqual( "A", Lambda.GetValue( expression ) );
        }

        /// <summary>
        /// 獲取成員值,委託返回型別為bool
        /// </summary>
        [TestMethod]
        public void TestGetValue_Boolean() {
            //空值返回null
            Assert.AreEqual( null, Lambda.GetValue( null ) );

            //一級返回值
            Expression<Func<Test1, bool>> expression = test => test.Name == "A";
            Assert.AreEqual( "A", Lambda.GetValue( expression ) );

            //二級返回值
            Expression<Func<Test1, bool>> expression2 = test => test.A.Integer == 1;
            Assert.AreEqual( 1, Lambda.GetValue( expression2 ) );

            //三級返回值
            Expression<Func<Test1, bool>> expression3 = test => test.A.B.Name == "B";
            Assert.AreEqual( "B", Lambda.GetValue( expression3 ) );
        }

        /// <summary>
        /// 獲取可空型別的值
        /// </summary>
        [TestMethod]
        public void TestGetValue_Nullable() {
            //可空整型
            Expression<Func<Test1, bool>> expression = test => test.NullableInt == 1;
            Assert.AreEqual( 1, Lambda.GetValue( expression ) );

            //可空decimal
            expression = test => test.NullableDecimal == 1.5M;
            Assert.AreEqual( 1.5M, Lambda.GetValue( expression ) );
        }

        /// <summary>
        /// 獲取成員值,運算子為方法
        /// </summary>
        [TestMethod]
        public void TestGetValue_Method() {
            //1級返回值
            Expression<Func<Test1, bool>> expression = t => t.Name.Contains( "A" );
            Assert.AreEqual( "A", Lambda.GetValue( expression ) );

            //二級返回值
            expression = t => t.A.Address.Contains( "B" );
            Assert.AreEqual( "B", Lambda.GetValue( expression ) );

            //三級返回值
            expression = t => t.A.B.Name.StartsWith( "C" );
            Assert.AreEqual( "C", Lambda.GetValue( expression ) );
        }

        /// <summary>
        /// 從例項中獲取值
        /// </summary>
        [TestMethod]
        public void TestGetValue_Instance() {
            var test = new Test1() { Name = "a", A = new Test1.TestA() { Address = "b", B = new Test1.TestA.TestB() { Name = "c" } } };

            //一級屬性
            Expression<Func<string>> expression = () => test.Name;
            Assert.AreEqual( "a", Lambda.GetValue( expression ) );

            //二級屬性
            Expression<Func<string>> expression2 = () => test.A.Address;
            Assert.AreEqual( "b", Lambda.GetValue( expression2 ) );

            //三級屬性
            Expression<Func<string>> expression3 = () => test.A.B.Name;
            Assert.AreEqual( "c", Lambda.GetValue( expression3 ) );
        }

        /// <summary>
        /// 測試值為複雜型別
        /// </summary>
        [TestMethod]
        public void TestGetValue_Complex() {
            var test = new Test1() { Name = "a", A = new Test1.TestA() { Address = "b" } };

            //獲取表示式的值
            Expression<Func<Test1, bool>> expression = t => t.Name == test.Name;
            Assert.AreEqual( "a", Lambda.GetValue( expression ), "==test.Name" );
            Expression<Func<Test1, bool>> expression2 = t => t.Name == test.A.Address;
            Assert.AreEqual( "b", Lambda.GetValue( expression2 ), "==test.A.Address" );

            //獲取方法的值
            Expression<Func<Test1, bool>> expression3 = t => t.Name.Contains( test.Name );
            Assert.AreEqual( "a", Lambda.GetValue( expression3 ), "Contains test.Name" );
            Expression<Func<Test1, bool>> expression4 = t => t.Name.Contains( test.A.Address );
            Assert.AreEqual( "b", Lambda.GetValue( expression4 ), "==test.A.Address" );
        }

        #endregion

        #region GetParameter(獲取引數)

        /// <summary>
        /// 獲取引數
        /// </summary>
        [TestMethod]
        public void TestGetParameter() {
            //空值返回null
            Assert.AreEqual( null, Lambda.GetParameter( null ) );

            //一級返回值
            Expression<Func<Test1, object>> expression = test => test.Name == "A";
            Assert.AreEqual( "test", Lambda.GetParameter( expression ).ToString() );

            //二級返回值
            Expression<Func<Test1, object>> expression2 = test => test.A.Integer == 1;
            Assert.AreEqual( "test", Lambda.GetParameter( expression2 ).ToString() );

            //三級返回值
            Expression<Func<Test1, object>> expression3 = test => test.A.B.Name == "B";
            Assert.AreEqual( "test", Lambda.GetParameter( expression3 ).ToString() );
        }

        #endregion

        #region GetCriteriaCount(獲取謂詞條件的個數)

        /// <summary>
        /// 獲取謂詞條件的個數
        /// </summary>
        [TestMethod]
        public void TestGetCriteriaCount() {
            //0個條件
            Assert.AreEqual( 0, Lambda.GetCriteriaCount( null ) );

            //1個條件
            Expression<Func<Test1, bool>> expression = test => test.Name == "A";
            Assert.AreEqual( 1, Lambda.GetCriteriaCount( expression ) );

            //2個條件,與連線符
            expression = test => test.Name == "A" && test.Name == "B";
            Assert.AreEqual( 2, Lambda.GetCriteriaCount( expression ) );

            //2個條件,或連線符
            expression = test => test.Name == "A" || test.Name == "B";
            Assert.AreEqual( 2, Lambda.GetCriteriaCount( expression ) );

            //3個條件
            expression = test => test.Name == "A" && test.Name == "B" || test.Name == "C";
            Assert.AreEqual( 3, Lambda.GetCriteriaCount( expression ) );

            //3個條件,包括導航屬性
            expression = test => test.A.Address == "A" && test.Name == "B" || test.Name == "C";
            Assert.AreEqual( 3, Lambda.GetCriteriaCount( expression ) );
        }

        /// <summary>
        /// 獲取謂詞條件的個數,運算子為方法
        /// </summary>
        [TestMethod]
        public void TestGetCriteriaCount_Method() {
            //1個條件
            Expression<Func<Test1, bool>> expression = t => t.Name.Contains( "A" );
            Assert.AreEqual( 1, Lambda.GetCriteriaCount( expression ) );

            //2個條件,與連線
            expression = t => t.Name.Contains( "A" ) && t.Name == "A";
            Assert.AreEqual( 2, Lambda.GetCriteriaCount( expression ) );

            //2個條件,或連線,包含導航屬性
            expression = t => t.Name.Contains( "A" ) || t.A.Address == "A";
            Assert.AreEqual( 2, Lambda.GetCriteriaCount( expression ) );
        }

        #endregion

        #region Equal(建立等於表示式)

        /// <summary>
        /// 建立等於表示式
        /// </summary>
        [TestMethod]
        public void TestEqual() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age == 1;
            Assert.AreEqual( expected.ToString(), Lambda.Equal<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer == 1;
            Assert.AreEqual( expected2.ToString(), Lambda.Equal<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region NotEqual(建立不等於表示式)

        /// <summary>
        /// 建立不等於表示式
        /// </summary>
        [TestMethod]
        public void TestNotEqual() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age != 1;
            Assert.AreEqual( expected.ToString(), Lambda.NotEqual<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer != 1;
            Assert.AreEqual( expected2.ToString(), Lambda.NotEqual<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region Greater(建立大於表示式)

        /// <summary>
        /// 建立大於表示式
        /// </summary>
        [TestMethod]
        public void TestGreater() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age > 1;
            Assert.AreEqual( expected.ToString(), Lambda.Greater<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer > 1;
            Assert.AreEqual( expected2.ToString(), Lambda.Greater<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region Less(建立小於表示式)

        /// <summary>
        /// 建立小於表示式
        /// </summary>
        [TestMethod]
        public void TestLess() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age < 1;
            Assert.AreEqual( expected.ToString(), Lambda.Less<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer < 1;
            Assert.AreEqual( expected2.ToString(), Lambda.Less<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region GreaterEqual(建立大於等於表示式)

        /// <summary>
        /// 建立大於等於表示式
        /// </summary>
        [TestMethod]
        public void TestGreaterEqual() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age >= 1;
            Assert.AreEqual( expected.ToString(), Lambda.GreaterEqual<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer >= 1;
            Assert.AreEqual( expected2.ToString(), Lambda.GreaterEqual<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region LessEqual(建立小於等於表示式)

        /// <summary>
        /// 建立小於等於表示式
        /// </summary>
        [TestMethod]
        public void TestLessEqual() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Age <= 1;
            Assert.AreEqual( expected.ToString(), Lambda.LessEqual<Test1>( "Age", 1 ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Integer <= 1;
            Assert.AreEqual( expected2.ToString(), Lambda.LessEqual<Test1>( "A.Integer", 1 ).ToString() );
        }

        #endregion

        #region Contains(呼叫Contains方法)

        /// <summary>
        /// 呼叫Contains方法
        /// </summary>
        [TestMethod]
        public void TestContains() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Name.Contains( "A" );
            Assert.AreEqual( expected.ToString(), Lambda.Contains<Test1>( "Name", "A" ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Address.Contains( "A" );
            Assert.AreEqual( expected2.ToString(), Lambda.Contains<Test1>( "A.Address", "A" ).ToString() );

            //三級屬性
            Expression<Func<Test1, bool>> expected3 = t => t.A.B.Name.Contains( "A" );
            Assert.AreEqual( expected3.ToString(), Lambda.Contains<Test1>( "A.B.Name", "A" ).ToString() );
        }

        #endregion

        #region Starts(呼叫StartsWith方法)

        /// <summary>
        /// 呼叫StartsWith方法
        /// </summary>
        [TestMethod]
        public void TestStarts() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Name.StartsWith( "A" );
            Assert.AreEqual( expected.ToString(), Lambda.Starts<Test1>( "Name", "A" ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Address.StartsWith( "A" );
            Assert.AreEqual( expected2.ToString(), Lambda.Starts<Test1>( "A.Address", "A" ).ToString() );

            //三級屬性
            Expression<Func<Test1, bool>> expected3 = t => t.A.B.Name.StartsWith( "A" );
            Assert.AreEqual( expected3.ToString(), Lambda.Starts<Test1>( "A.B.Name", "A" ).ToString() );
        }

        #endregion

        #region Ends(呼叫EndsWith方法)

        /// <summary>
        /// 呼叫EndsWith方法
        /// </summary>
        [TestMethod]
        public void TestEnds() {
            //一級屬性
            Expression<Func<Test1, bool>> expected = t => t.Name.EndsWith( "A" );
            Assert.AreEqual( expected.ToString(), Lambda.Ends<Test1>( "Name", "A" ).ToString() );

            //二級屬性
            Expression<Func<Test1, bool>> expected2 = t => t.A.Address.EndsWith( "A" );
            Assert.AreEqual( expected2.ToString(), Lambda.Ends<Test1>( "A.Address", "A" ).ToString() );

            //三級屬性
            Expression<Func<Test1, bool>> expected3 = t => t.A.B.Name.EndsWith( "A" );
            Assert.AreEqual( expected3.ToString(), Lambda.Ends<Test1>( "A.B.Name", "A" ).ToString() );
        }

        #endregion

        #region GetConst(獲取常量表示式)

        /// <summary>
        /// 獲取常量表示式
        /// </summary>
        [TestMethod]
        public void TestGetConst() {
            Expression<Func<Test1, int?>> property = t => t.NullableInt;
            ConstantExpression constantExpression = Lambda.Constant( property, 1 );
            Assert.AreEqual( typeof( int ), constantExpression.Type );
        }

        #endregion

        #region GetAttribute(獲取特性)

        /// <summary>
        /// 測試獲取特性
        /// </summary>
        [TestMethod]
        public void TestGetAttribute() {
            DisplayAttribute attribute = Lambda.GetAttribute<Test1, string, DisplayAttribute>( t => t.Name );
            Assert.AreEqual( "名稱", attribute.Name );
        }

        #endregion

        #region GetAttributes(獲取特性列表)

        /// <summary>
        /// 測試獲取特性列表
        /// </summary>
        [TestMethod]
        public void TestGetAttributes() {
            IEnumerable<ValidationAttribute> attributes = Lambda.GetAttributes<Test1, string, ValidationAttribute>( t => t.Name );
            Assert.AreEqual( 2, attributes.Count() );
        }

        #endregion
    }
}

  這些操作方法的作用,大家自己看下測試就明白了,具體應用在後面介紹。

  .Net應用程式框架交流QQ群: 386092459,歡迎有興趣的朋友加入討論。

  謝謝大家的持續關注,我的部落格地址:http://www.cnblogs.com/xiadao521/

  下載地址:http://files.cnblogs.com/xiadao521/Util.2015.1.6.1.rar

轉載於:https://www.cnblogs.com/xiadao521/p/4206696.html

相關文章