1. 程式人生 > >Lind.DDD.ExpressionExtensions動態構建表示式樹,實現對資料集的許可權控制

Lind.DDD.ExpressionExtensions動態構建表示式樹,實現對資料集的許可權控制

回到目錄

Lind.DDD框架裡提出了對資料集的控制,某些許可權的使用者為某些表新增某些資料集的許可權,具體實現是在一張表中儲存使用者ID,表名,檢索欄位,檢索值和檢索操作符,然後使用者登陸後,通過自己許可權來構建對應表的查詢語句,即動態構建表示式樹,這種操作一些被寫在業務層上,我們可以在業務層需要進行資料集許可權控制的地方,新增這種策略,下面具體分析說明一下.

看一下資料集許可權表結果

  public class User_DataSet_Policies
    {
        /// <summary>
        /// 使用者ID
        /// </summary>
public int UserId { get; set; } /// <summary> /// 表名 /// </summary> public string TableName { get; set; } /// <summary> /// 策略所需欄位 /// </summary> public string PolicyField { get; set; } /// <summary> ///
策略所需要值 /// </summary> public string PolicyValue { get; set; } /// <summary> /// 策略操作符 /// </summary> public string PolicyOperation { get; set; } }

看一下,在程式中如何動態構建和使用我們的表示式樹

        Expression<Func<User, bool>> exe = ExpressionExtensions.GenerateExpression<User>(
                
new string[] { "Age", "UserName" }, new object[] { "12", "zzl" }, new string[] { "=", "=" }); userList.Where(exe.Compile()).ToList().ForEach(i => { Console.WriteLine(i.UserName); });

下面貢獻一下GenerateExpression泛型方法的原碼,大家可以把它新增到我們的LinqExtensions模組裡

   /// <summary>
    /// 表示式樹的擴充套件
    /// </summary>
    public class ExpressionExtensions
    {
        /// <summary>
        /// 構建表示式樹
        /// 呼叫:GenerateExpression(new string[]{"username"},new object[]{"zzl"},new string[]{"="});
        /// </summary>
        /// <typeparam name="T">表型別</typeparam>
        /// <param name="keys">欄位名</param>
        /// <param name="values">欄位值</param>
        /// <param name="operation">操作符</param>
        /// <returns></returns>
        public static Expression<Func<T, bool>> GenerateExpression<T>(string[] keys, object[] values, string[] operation)
        {
            var TType = typeof(T);
            Expression expression_return = Expression.Constant(true);
            ParameterExpression expression_param = Expression.Parameter(TType, "p");
            Expression expression;
            for (int i = 0; i < keys.Length; i++)
            {
                switch (operation[i])
                {
                    case "=":
                        expression = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            TType.GetMethod("ToString")),
                         Expression.Constant(values[i]));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case "%":
                        expression = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            typeof(string).GetMethod("Contains"),
                            Expression.Constant(values[i], typeof(string)));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case ">":
                        expression = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            typeof(double).GetType().GetMethod("GreaterThan"), Expression.Constant(values[i]));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case "<":
                        expression = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            typeof(double).GetType().GetMethod("LessThan"), Expression.Constant(values[i]));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case ">=":
                        expression = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            typeof(double).GetType().GetMethod("GreaterThanOrEqual"), Expression.Constant(values[i]));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case "<=":
                        expression = Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                            TType.GetProperty(keys[i]).GetType().GetMethod("LessThanOrEqual"), Expression.Constant(values[i]));
                        expression_return = Expression.And(expression_return, expression);
                        break;
                    case "in":
                        string[] strarr = values[i].ToString().Split(',');
                        Expression or_return = Expression.Constant(false);
                        for (int k = 0; k < strarr.Length; k++)
                        {
                            expression = Expression.Equal(Expression.Call(Expression.Property(expression_param, TType.GetProperty(keys[i])),
                                TType.GetMethod("ToString")),
                             Expression.Constant(strarr[k]));
                            or_return = Expression.Or(or_return, expression);
                        }

                        expression_return = Expression.And(expression_return, or_return);
                        break;
                    default:
                        throw new ArgumentException("無效的操作符,目前只支援=,%,>,<,>=,<=,in");
                }
            }

            return (Expression<Func<T, bool>>)Expression.Lambda<Func<T, bool>>(expression_return, new ParameterExpression[] { expression_param });
        }
    }

對於動態構建表示式的介紹就到這裡了,以後在使用過程中如果出現什麼問題,請直接回復我.

回到目錄