LINQ:将lambda表达式作为参数传递,由方法执行并返回

时间:2009-08-19 12:14:04

标签: c# linq

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

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

这基本上是我要做的事情:

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

3 个答案:

答案 0 :(得分:64)

这样的事情:

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. 如果需要,您知道如何修改谓词表达式。

答案 1 :(得分:12)

以下是如何将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);
        }
    }
}

答案 2 :(得分:6)

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

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

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