【问题标题】:LINQ: Passing lambda expression as parameter to be executed and returned by methodLINQ:将 lambda 表达式作为参数传递给方法执行和返回
【发布时间】:2009-08-19 12:14:04
【问题描述】:

这里是这样的场景:我有一系列不同的存储库类,每个类都可以使用隔离的数据上下文或共享的上下文。在使用隔离上下文的情况下,我想向基类添加一个方法,该方法允许我将 lambda 指定为参数,让该表达式由所选存储库的隔离上下文执行并返回 IQueryable 结果.方法签名的外观如何,以及如何将表达式传递给上下文?

我需要尽可能通用的解决方案,因为可以使用任何可能的模型对象/表。

这基本上是我想做的:

IAssetRepository repo = new AssetRepository(true); // true indicates isolated context
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x => 
                                              x.SomeProp.Equals(SomeValue)));

【问题讨论】:

    标签: c# linq


    【解决方案1】:

    类似这样的:

    public IEnumerable<T> ExecuteInContext<T>(
      Expression<Func<T,bool>> predicate)
    {
      ... // do your stuff
      //eg
      Table<T> t = GetTable<T>();
      return t.Where(predicate);
    }
    

    public IEnumerable<T> ExecuteInContext<T>(
       IQueryable<T> src, Expression<Func<T,bool>> predicate)
    {
      return src.Where(predicate);
    }
    

    用法:

    var r = repo.ExecuteInContext<SomeType>( 
              x => x.SomeProp.Equals(Somevalue));
    

    var r = repo.ExecuteInContext(GetTable<T>(), 
              x => x.SomeProp.Equals(Somevalue));
    

    假设:

    1. 表可以从 T 派生,否则您也需要传递源。
    2. 如果需要,您知道如何修改谓词表达式。

    【讨论】:

    • 在尝试您的第一个建议时,我在编译 Table t = GetTable(); 时遇到错误line: T 必须是引用类型才能将其用作参数
    • 没关系,我明白了。需要在方法声明的末尾添加“where T : class”。
    • 这可能使用 LINQ 查询语法吗?我不能让from x in y where predicate select z 工作。
    【解决方案2】:

    这是一个完整的工作示例,如何将 LINQ 表达式作为参数传递

    using System;
    using System.Linq.Expressions;
    using System.Reflection;
    
    namespace ConsoleTest
    {
        public class Values
        {
            public int X { get; set; }
            public int Y { get; set; }
    
            public override string ToString()
            {
                return String.Format("[ X={0} Y={1} ]", X, Y);
            }
        }
    
        class Program
        {
            static void Main()
            {
                var values = new Values {X = 1, Y = 1};
    
                // pass parameter to be incremented as linq expression
                IncrementValue(values, v => v.X);
                IncrementValue(values, v => v.X);
                IncrementValue(values, v => v.Y);
    
                // Output is: [ X=3 Y=2 ]
                Console.Write(values);
            }
    
            private static void IncrementValue<T>(T obj, Expression<Func<T,int>> property)
            {
                var memberExpression = (MemberExpression)property.Body;
                var propertyInfo = (PropertyInfo)memberExpression.Member;
                // read value with reflection
                var value = (int)propertyInfo.GetValue(obj, null);
                // set value with reflection
                propertyInfo.SetValue(obj, ++value, null);
            }
        }
    }
    

    【讨论】:

    • 此答案顶部的链接已损坏。
    • 链接已删除。代码示例提供了答案
    【解决方案3】:

    查看 PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx

    此代码会将您的 where 子句打包为您可以传递的 Expression 对象。

    我已经实现了 Repository 模式,我的 flava 是给它一个 Fetch(ICriteria) 方法,它根据提供的条件构建 Where 子句。简单,但对我有用。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-27
      • 1970-01-01
      • 2019-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多