C# LINQ:将 lambda 表达式作为要执行的参数并由方法返回
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1299534/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
LINQ: Passing lambda expression as parameter to be executed and returned by method
提问by Jason Miesionczek
So here is the scenario: i have a series of different repository classes that each can use an isolated data context, or a shared context. In the cases where an isolated context is being used i want to add a method to the base class that will allow me to specify the lambda as the parameter, have that expression be executed by the isolated context of the chosen repository and return an IQueryable result. How would the method signature look, and how to a pass the expression to the context?
所以这里是场景:我有一系列不同的存储库类,每个类都可以使用独立的数据上下文或共享上下文。在使用隔离上下文的情况下,我想向基类添加一个方法,该方法允许我将 lambda 指定为参数,让该表达式由所选存储库的隔离上下文执行并返回 IQueryable 结果. 方法签名看起来如何,以及如何将表达式传递给上下文?
I need the solution to be as generic as possible as any possible model object/table could be used.
我需要解决方案尽可能通用,因为可以使用任何可能的模型对象/表。
Here is basically what i am looking to do:
这基本上是我想要做的:
IAssetRepository repo = new AssetRepository(true); // true indicates isolated context
var results = repo.ExecuteInContext<SomeType>(SomeTable.Where(x =>
x.SomeProp.Equals(SomeValue)));
采纳答案by leppie
Something like this:
像这样的东西:
public IEnumerable<T> ExecuteInContext<T>(
Expression<Func<T,bool>> predicate)
{
... // do your stuff
//eg
Table<T> t = GetTable<T>();
return t.Where(predicate);
}
or
或者
public IEnumerable<T> ExecuteInContext<T>(
IQueryable<T> src, Expression<Func<T,bool>> predicate)
{
return src.Where(predicate);
}
Usage:
用法:
var r = repo.ExecuteInContext<SomeType>(
x => x.SomeProp.Equals(Somevalue));
or
或者
var r = repo.ExecuteInContext(GetTable<T>(),
x => x.SomeProp.Equals(Somevalue));
Assumptions:
假设:
- Table can be derived from T, else you will need to pass the source too.
- You know how to modify the predicate expression if needed.
- 表可以从 T 派生,否则您也需要传递源。
- 如果需要,您知道如何修改谓词表达式。
回答by Duncan
Check out PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx
查看 PredicateBuilder - http://www.albahari.com/nutshell/predicatebuilder.aspx
This code will package up your where clause as Expression objects which you can pass about.
此代码将您的 where 子句打包为您可以传递的 Expression 对象。
I've implemented the Repository pattern, and my flava is to give it a Fetch(ICriteria) method, which builds up the Where clause depending on the criteria supplied. Simple, but works for me.
我已经实现了 Repository 模式,我的方法是给它一个 Fetch(ICriteria) 方法,它根据提供的标准构建 Where 子句。简单,但对我有用。
回答by Maksym Kozlenko
Here is a complete working sample how to pass LINQ expression as a parameter
这是一个完整的工作示例如何将 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);
}
}
}