none
求问关于Func<T,bool>的使用 RRS feed

  • 问题

  • 下面条件一和条件二是分开产生的,后面会将funcFilter作为参数传给其他函数,但是事实上funcFilter并不是我想要的,因为只执行了条件二,只执行最后一个条件;

    我希望作为参数传值时为:funcFilter+=c->c.Name.Contains("a") && c.Age>15;请问如何实现我想要的结果!!!

    class T
    {
    int Id;
    string Name;
    int Age;
    }

    Func<T,bool> funcFilter=null;//过滤条件
    funcFilter+=c=>c.Name.Contains("a");//条件一
    funcFilter+=c=>c.Age>15;//条件二


    证明自己存在

    2012年4月21日 14:18

答案

  • 您好,

    请参考以下的方式试看看!

    1.建一个Expression的扩展方法 (要using System.Linq.Expressions;)哦!

    //using System.Linq.Expressions;

    public static class MyExpressionExtension { //copy from http://stackoverflow.com/questions/457316/combining-two-expressions-expressionfunct-bool public static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { // need to detect whether they use the same // parameter instance; if not, they need fixing ParameterExpression param = expr1.Parameters[0]; if (ReferenceEquals(param, expr2.Parameters[0])) { // simple version return Expression.Lambda<Func<T, bool>>( Expression.AndAlso(expr1.Body, expr2.Body), param); } // otherwise, keep expr1 "as is" and invoke expr2 return Expression.Lambda<Func<T, bool>>( Expression.AndAlso( expr1.Body, Expression.Invoke(expr2, param)), param); } }


    2.建立Expression,然后使用那个扩展方法,来处理AndAlso,如下!

    Expression<Func<T, bool>> expr1 = c => c.Name.Contains("a");//条件一
    Expression<Func<T, bool>> expr2 = c => c.Age > 15;//条件二
    Expression<Func<T, bool>> expr3 = expr1.AndAlso(expr2);
    Func<T, bool> funcF3 = expr3.Compile();
    var result = funcF3(new T() { Age = 16, Id = 1, Name = "ccc" }); // false
    MessageBox.Show("Age = 16, Id = 1, Name = ccc : " + result.ToString());
    result = funcF3(new T() { Age = 16, Id = 1, Name = "aaa" }); // true
    MessageBox.Show("Age = 16, Id = 1, Name = aaa : " + result.ToString()); 
    result = funcF3(new T() { Age = 11, Id = 1, Name = "aaa" }); // false
    MessageBox.Show("Age = 11, Id = 1, Name = aaa : " + result.ToString());
    result = funcF3(new T() { Age = 11, Id = 1, Name = "aaa" }); // false
    MessageBox.Show("Age = 11, Id = 1, Name = bbb : " + result.ToString()); 

    希望对您有帮助,谢谢!

    Ref:Combining two expressions (Expression<Func<T, bool>>)


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/



    2012年4月23日 5:11

全部回复

  • 你不能使用+=,Func<……>是一个委托,你不得不重复执行两次该委托,而且不是并列条件。如果要并列,请用“&”连接:

    class T
    {
    int Id;
    string Name;
    int Age;
    }
    
    Func<T,bool> funcFilter=null;
    funcFilter=(c)=>(c.Name.Contains("a") && c.Age>15);
    

       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    2012年4月22日 1:35
    版主
  • 您好,

    请参考以下的方式试看看!

    1.建一个Expression的扩展方法 (要using System.Linq.Expressions;)哦!

    //using System.Linq.Expressions;

    public static class MyExpressionExtension { //copy from http://stackoverflow.com/questions/457316/combining-two-expressions-expressionfunct-bool public static Expression<Func<T, bool>> AndAlso<T>( this Expression<Func<T, bool>> expr1, Expression<Func<T, bool>> expr2) { // need to detect whether they use the same // parameter instance; if not, they need fixing ParameterExpression param = expr1.Parameters[0]; if (ReferenceEquals(param, expr2.Parameters[0])) { // simple version return Expression.Lambda<Func<T, bool>>( Expression.AndAlso(expr1.Body, expr2.Body), param); } // otherwise, keep expr1 "as is" and invoke expr2 return Expression.Lambda<Func<T, bool>>( Expression.AndAlso( expr1.Body, Expression.Invoke(expr2, param)), param); } }


    2.建立Expression,然后使用那个扩展方法,来处理AndAlso,如下!

    Expression<Func<T, bool>> expr1 = c => c.Name.Contains("a");//条件一
    Expression<Func<T, bool>> expr2 = c => c.Age > 15;//条件二
    Expression<Func<T, bool>> expr3 = expr1.AndAlso(expr2);
    Func<T, bool> funcF3 = expr3.Compile();
    var result = funcF3(new T() { Age = 16, Id = 1, Name = "ccc" }); // false
    MessageBox.Show("Age = 16, Id = 1, Name = ccc : " + result.ToString());
    result = funcF3(new T() { Age = 16, Id = 1, Name = "aaa" }); // true
    MessageBox.Show("Age = 16, Id = 1, Name = aaa : " + result.ToString()); 
    result = funcF3(new T() { Age = 11, Id = 1, Name = "aaa" }); // false
    MessageBox.Show("Age = 11, Id = 1, Name = aaa : " + result.ToString());
    result = funcF3(new T() { Age = 11, Id = 1, Name = "aaa" }); // false
    MessageBox.Show("Age = 11, Id = 1, Name = bbb : " + result.ToString()); 

    希望对您有帮助,谢谢!

    Ref:Combining two expressions (Expression<Func<T, bool>>)


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/



    2012年4月23日 5:11
  • 我知道您的意思,但是我的那两个条件是必须分开产生的,不可能拿到一起。


    证明自己存在

    2012年4月23日 13:10
  • 您好,

    以下程序可分开产生哦! expr1.AndAlso(expr2)

    Expression<Func<T, bool>> expr1 = c => c.Name.Contains("a");//条件一
    Expression<Func<T, bool>> expr2 = c => c.Age > 15;//条件二
    Expression<Func<T, bool>> expr3 = expr1.AndAlso(expr2);


    以上說明若有錯誤請指教,謝謝。
    亂馬客blog: http://www.dotblogs.com.tw/rainmaker/

    2012年4月23日 16:20
  • 我知道您的意思,但是我的那两个条件是必须分开产生的,不可能拿到一起。


    证明自己存在

    你的“分开产生”什么意思?

    1)如果是“分别满足”,使用Or(||):

    Func<T,bool> funcFilter=null
    funcFilter=(c)=>(c.Name.Contains("a") || c.Age>15);

    2)如果是执行两次,那么使用Foreach循环:

    namespace MyTest
    {
        public class T
        {
           public int Id{get;set;}
           public string Name { get; set; }
           public int Age { get; set; }
        }
    
    
        class Program
        {
            static void Main(string[] args)
            {
                Func<T, bool> funcFilter = null;
                funcFilter = new Func<T, bool>(c => c.Name.Contains("c"));  //条件1
                funcFilter+=c=>c.Age>15;//条件二
                T t = new T() { Id = 1, Name = "abc", Age = 15 };
    
                foreach (var item in funcFilter.GetInvocationList())
                {
                    Console.WriteLine(item.DynamicInvoke(t));
                }
            }
        }
    }


       QQ我:讨论(Talk)
    下载MSDN桌面工具(Vista,Win7)
    我的博客园
    慈善点击,点击此处

    • 已建议为答案 亂馬客 2012年4月24日 2:37
    2012年4月24日 1:31
    版主
  • 可以写一个条件的封装类实现

        public class MyCriteria<T>
        {
            public Func<T, bool> Criteria1 { get; set; }

            public Func<T, bool> Criteria2 { get; set; }

            public MyCriteria()
            {

            }

            public bool GetResult(T pParam)
            {
                return this.Criteria1(pParam) && this.Criteria2(pParam);
            }
        }

    ...............

    然后

    MyCriteria _criteria = new MyCriteria();

    _criteria.Criteria1 = c=>c.Name.Contains("a");//条件一

    /////然后将 _criteria实例传递或保留到可以获取条件二的时刻。

    _critera.Criteria2 = c=>c.Age>15;//条件二

    --最后

    funcFilter = _criteria.GetResult;


    DON'T TRY SO HARD,THE BEST THINGS COME WHEN YOU LEAST EXPECT THEM TO.

    • 已建议为答案 亂馬客 2012年4月24日 2:38
    2012年4月24日 2:26