假设我们需要应用几个条件来从一个名为"Things"的表中进行选择(未知计数和性质)
如果条件已知,我们可以写
db.Things.Where(t=>foo1 && foo2 || foo3);
Run Code Online (Sandbox Code Playgroud)
但是如果我们必须以编程方式构建Where条件,我可以想象我们如何应用ANDed条件
IQuerable DesiredThings = db.Things.AsQuerable();
foreach (Condition c in AndedConditions)
DesiredThings = DesiredThings.Where(t => GenerateCondition(c,t));
Run Code Online (Sandbox Code Playgroud)
ORed条件怎么样?注意:我们不想执行union,unique或任何其他代价高昂的操作,我们希望生成一个查询,好像我们将它写成ad-hock
提前致谢.
PredicateBuilder:动态编写表达式谓词
这不是"接近实际"的情况,但它表明如果在源类型中找到合适的运算符,Expressions API不会在目标转换类型中查找运算符.
sealed class Foo
{
public static explicit operator Bar(Foo foo) { return null; }
}
sealed class Bar
{
public static implicit operator Bar(Foo foo) { return null; }
}
class Program
{
public static void Blah(Bar bar) { }
private static void Main()
{
Expression<Func<Foo, Bar>> expr1 = x => x;
// fine, used implicit operator from Bar
var param = Expression.Parameter(typeof(Foo), "x");
var expr2 = Expression.Lambda<Func<Foo, Bar>>(
Expression.Convert(param, typeof(Bar)),
param);
// fine, but used explicit operator …Run Code Online (Sandbox Code Playgroud) 我使用此代码使用IronPython执行python表达式.
ScriptEngine engine = Python.CreateEngine();
ScriptScope scope = engine.CreateScope();
scope.SetVariable("m", mobject);
string code = "m.ID > 5 and m.ID < 10";
ScriptSource source =
engine.CreateScriptSourceFromString(code, SourceCodeKind.Expression);
source.Execute(scope);
Run Code Online (Sandbox Code Playgroud)
有没有办法将生成的表达式树作为c#对象,例如BlockExpression
?
类似于约翰K的问题,但更具体和接受的答案不符合我的需要.
编译好:
Expression<Func<object, object>> specificExpression = (object o) => new object();
Expression generalExpression = specificExpression;
Run Code Online (Sandbox Code Playgroud)
而这个不是:
Expression generalExpression = (object o) => new object();
Run Code Online (Sandbox Code Playgroud)
报告编译错误:
Cannot convert lambda expression to type 'System.Linq.Expressions.Expression' because it is not a delegate type
Expression<Func<T1,T2>>来源于Expression.
现在我有一个框架,方法接受各种表达式,即类型Expression.被迫Expression<Func<T1,T2>>在每个方法调用中显式地将lambdas强制转换为相应的是令人沮丧的.
在这种情况下,为什么这个基本的OOP行为被打破了?
可能重复:
如何将LINQ表达式合并为一个?
public bool IsUnique(params Expression<Func<Employee, bool>>[] properties)
{
var combinedProperties = Combine(properties);
var rowCount = _session.QueryOver<Employee>().Where(combinedProperties).ToRowCountQuery().RowCount();
return rowCount == 0;
}
Expression<Func<Employee, bool>> Combine(Expression<Func<Employee, bool>>[] properties)
{
???
}
Run Code Online (Sandbox Code Playgroud)
用法:
var isUnique = _employeeRepository.IsUnique(x => x.FirstName == commandMessage.FirstName, x => x.LastName == commandMessage.LastName);
Run Code Online (Sandbox Code Playgroud)
有没有一种方法将谓词与AND运算符相结合?
我试图ToLower使用下面的Expression调用将字符串转换为case.
var tolowerMethod = typeof(string).GetMethods().Where(m => m.Name == "ToString").FirstOrDefault();
var toLowerMethodCall = Expression.Call(memExp,tolowerMethod,new Expression[0]);
Run Code Online (Sandbox Code Playgroud)
我面临一些问题,要创建一个Expression调用来格式化一个值,如:"05/12/2012 12:00:00"to {0:MM/dd/yyyy}.
我最终尝试运行查询时收到以下错误
"IsFalse"类型的未知LINQ表达式
这是代码
private static IQueryable<T> QueryMethod<T>(
IQueryable<T> query,
QueryableRequestMessage.WhereClause.Rule rule,
Type type,
string methodName,
Expression property,
Expression value,
string op,
ParameterExpression parameter
) where T : class
{
var methodInfo = type.GetMethod(methodName, new[] { type });
var call = Expression.Call(property, methodInfo, value);
var expression = rule.Op.Equals(op)
? Expression.Lambda<Func<T, bool>>(call, parameter)
: Expression.Lambda<Func<T, bool>>(Expression.IsFalse(call), parameter);
query = query.Where(expression);
return query;
}
Run Code Online (Sandbox Code Playgroud)
重要变量具有以下值
query: an IQueryable that I am building up
type: String
methodName: "EndsWith"
rule.Op: "ne" //Not Ends With
op: …Run Code Online (Sandbox Code Playgroud) 当我尝试编译下面显示的lambda时,它抛出:
类型为'System.Collections.Generic.IEnumerable`1 [WheelEndCatalogKendo.Models.SapBasicData]'的变量'model''从范围''引用,但未定义
public static GridBoundColumnBuilder<TModel> BuildColumnString<TModel>(this GridBoundColumnBuilder<TModel> column, WebViewPage<IEnumerable<TModel>> webViewPage, int width) where TModel : class {
var modelParameter = Expression.Parameter(typeof(IEnumerable<TModel>), "model");
Expression<Func<IEnumerable<TModel>, TModel>> firstItem = (model) => model.FirstOrDefault();
var member = MemberExpression.Property(firstItem.Body, column.Column.Member);
var lambda = Expression.Lambda<Func<IEnumerable<TModel>, string>>(member, modelParameter);
var title = webViewPage.Html.DisplayNameFor(lambda).ToHtmlString();
var header = webViewPage.Html.ShortLabelFor(lambda).ToHtmlString().FixUpNewLinesAsHtml();
var compiled = lambda.Compile(); //Throws here with "variable '...' of type '...' referenced from scope '', but it is not defined"
....
}
Run Code Online (Sandbox Code Playgroud)
我看到几个类似的帖子; 但到目前为止,他们还没有告诉我我的代码问题.看起来我正在提供lambda变量(作为第二个参数参数).然而,我几乎没有创作表达树的经验.
有任何想法吗?
给定Msdn:一个constant-expression是一个可以在编译时完全评估的表达式.
但是在下面的示例代码中,我有一个无法在编译时评估的contantExpression.
我应该错过什么,但是什么?
public class SomeClass
{
public string Key { get; set; }
}
public static void Sample()
{
var wantedKey = Console.ReadLine();
Expression<Func<SomeClass, bool>> expression = c => c.Key == wantedKey;
var maybeAConstantExpression = ((MemberExpression)((BinaryExpression)expression.Body).Right).Expression;
//Both are true, so we have a constantExpression,righ and Value should be known
Console.WriteLine(maybeAConstantExpression.NodeType == ExpressionType.Constant);
Console.WriteLine(maybeAConstantExpression.GetType() == typeof(ConstantExpression));
var constantExpression = ((ConstantExpression)maybeAConstantExpression);
var constantValue = constantExpression.Value;
//ConsoleApplication1.Program+<>c__DisplayClass0
//Do not looks like a constant..this is a class...
Console.WriteLine(constantValue);
var fakeConstantValue = constantValue.GetType().GetField("wantedKey").GetValue(constantValue);
//Return …Run Code Online (Sandbox Code Playgroud) 我正在使用以下代码创建和缓存属性访问者委托:
static Delegate CreateGetterDelegate<T>(PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
var instance = Expression.Parameter(propertyInfo.DeclaringType);
var property = Expression.Property(instance, propertyInfo);
var convert = Expression.TypeAs(property, typeof(object));
return (Func<T, object>)Expression.Lambda(convert, instance).Compile();
}
Run Code Online (Sandbox Code Playgroud)
这是工作和运作良好(谢谢StackOverflow!),但是我想通过返回T和对象的Func来删除所需的装箱/拆箱.有没有办法改变返回,以便返回类型是T的Func和typeofproperty?
即
static Delegate CreateGetterDelegate<T>(PropertyInfo propertyInfo)
{
if (typeof(T) != propertyInfo.DeclaringType)
{
throw new ArgumentException();
}
... some magic happening here ...
return (Func<T, typeofproperty>)Expression.Lambda(...more magic...).Compile();
}
Run Code Online (Sandbox Code Playgroud)
注意 - 我正在使用VS2013和.NET 4.5
expression-trees ×10
c# ×8
linq ×3
.net ×2
lambda ×2
expression ×1
ironpython ×1
linq-to-sql ×1
properties ×1