我有一个查询,像这样:
var query = from sessions in dataSet
where (names.Contains(sessions.Username))
where (sessions.Login.TimeOfAction == dt)
select new { sessions.Username,
sessions.Login,
sessions.Logout, sessions.Duration };
Run Code Online (Sandbox Code Playgroud)
我想实现一个ExpressionVisitor来提取where子句作为Lambda,但到目前为止只能使用一个名为'InnermostWhereFinder'的类来获得第一个,该类来自TerraServer Web服务的自定义查询提供程序上的MSDN教程.
它是:
internal class InnermostWhereFinder : ExpressionVisitor
{
private MethodCallExpression innermostWhereExpression;
public MethodCallExpression GetInnermostWhere(Expression expression)
{
Visit(expression);
return innermostWhereExpression;
}
protected override Expression VisitMethodCall(MethodCallExpression expression)
{
if (expression.Method.Name == "Where")
innermostWhereExpression = expression;
Visit(expression.Arguments[0]);
return expression;
}
}
Run Code Online (Sandbox Code Playgroud)
我曾经尝试过大量调整这个类来返回两个没有成功的子句.找不到任何关于此的好文档,任何人都可以帮忙吗?我认为这最终需要产生多个可以使用的LambdaExpression对象.
假设我有以下功能
Dal.Person.GetAllByAge<T>(int iAge, Expression<Func<Person, T>> OrderBy)
Run Code Online (Sandbox Code Playgroud)
我想为表达式传递一个默认参数,如 OrderBy = e=>e.ID,
以便如果未定义此参数,则默认值是按 id 排序。
这怎么可能?
我正在做一个命令行计算器,所以我需要解析表达式.
calc 2*(3+4)*5
Run Code Online (Sandbox Code Playgroud)
我已完成扫描仪步骤,返回令牌的数组.现在我正处于解析器步骤.但是我不清楚如何做一个解析器/表达式树.
这就是我到目前为止所做的一切:
NODE* create_node(TOKEN* t) {
NODE* n = (NODE*)malloc(sizeof(NODE));
n->t = t;
n->l = n->r = 0;
return n;
}
void insert_node(NODE** top, NODE** n) {
if (!*top) {
*top = *n;
return;
}
if (!(*top)->l) insert_node(&(*top)->l, n);
else
if (!(*top)->r) insert_node(&(*top)->r, n);
else
insert_node(&(*top)->l, n);
}
Run Code Online (Sandbox Code Playgroud)
然后我传递令牌数组,如:
while (*tokens != 0) {
NODE* n = create_node(*tokens++);
insert_node(&root, &n);
}
Run Code Online (Sandbox Code Playgroud)
你可以看到我的树只向左抬起.我不知道如何通过顶部的操作员和数字作为叶子(包括运算符优先顺序)进行排序.
我会很感激启发,也喜欢编程(代码)术语.
如何Expression动态创建树时创建强制转换?
问题是,我有一个类型的属性string:
public class Test
{
public string Id { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
我想一般创建一个强类型的lambda表达式,表示一个委托,它返回一个object而不是a string(Expression<Func<T, object>>).
现在我这样做:
private static Expression<Func<T, object>> CreateIdQuery()
{
Type type = typeof(T);
PropertyInfo idProperty = type.GetProperty("Id");
ParameterExpression lambdaParam = Expression.Parameter(type, "x");
MemberExpression body = Expression.Property(lambdaParam, idProperty);
LambdaExpression expr = Expression.Lambda(body, lambdaParam);
return (Expression<Func<T, object>>)expr;
}
Run Code Online (Sandbox Code Playgroud)
但它在最后一行引发异常(我无法Expression<Func<Test, string>>转换Expression<Func<Test, object>>).
我如何施放表达式的主体(我假设该MemberExpression部分需要被投入一个object)?
我知道怎么做:
Expression body = Expression.Call(selector.Body, "Contains", null,
Expression.Constant("cats", typeof(string)));
Run Code Online (Sandbox Code Playgroud)
由于'contains'返回true/false,因此没有问题.
但是,我如何进行IndexOf并查看结果是否大于5?
Expression body = Expression.Call(selector.Body, "IndexOf", null,
Expression.Constant("cats", typeof(string)));
Run Code Online (Sandbox Code Playgroud) DisplayNameFor(x=>x.Title)ASP.Net MVC 中有一个助手。我想实现类似的行为。
我想要一个方法,它接受基于User类(u=>u.Birthdate或 u=>u.Name)的表达式、一个操作数(更大、更少、等于)和一个类似的值DateTime.Now并返回一个表达式 u=>u.Birthdate > DateTime.Now
我知道我必须从片段手动构建结果表达式。我无法理解的是传入和处理属性表达式。
编辑:
我想调用一个方法,如
GetFilterPredicate(u=>u.Birthdate,FilterOps.GreaterThan,DateTime.Parse("01.01.2013")
或
GetFilterPredicate(u=>u.SomeIntProperty,FilterOps.Equals,2)
更新:我已经创建了一个 repo 来解决这个问题以及一个集合属性过滤 https://github.com/Alexander-Taran/Lambda-Magic-Filters
我想动态获取和设置对象属性,如下所示:
public class Person
{
public string Name {get; set; }
}
public class Testing
{
public void Run()
{
var p = new Person();
SetValue(p, "Name", "Henry");
var name = GetValue(p, "Name");
}
}
Run Code Online (Sandbox Code Playgroud)
请问我可以获得使用动态方法(或表达式树)创建 GetValue 和 SetValue 方法的帮助吗?
我打算将编译后的表达式保存在字典中,以加快将来的 get/set 调用速度。
如果传递两个字符串,我有一段代码可以正常工作.由于某种原因,如果将GUID转换为字符串,它将无法正常工作.
更详细的说,如果我创建一个新的ExpandoObject并传递字符串值,它可以工作,但如果我将GUID转换为字符串,则不会.
下面的代码应该比较两个参数.在我的例子中,我传递了相同的两个字符串.对于Equal运算符,true如果字符串相同则应该返回.如果第二个参数GUID转换为字符串,则返回false偶数字符串是相同的.dynamicObj.Add(memberName, Guid.Parse(value).ToString());
不知道我错过了什么.这是我的代码.
string value = "642188c7-8e10-e111-961b-0ee1388ccc3b";
string memberName = "State";
string contactValue = value;
var dynamicObj = (IDictionary<string, object>)new ExpandoObject(); dynamicObj.Add(memberName, Guid.Parse(value).ToString());
var expression = Expression.Parameter(typeof(object), "arg");
var binder = Binder.GetMember(CSharpBinderFlags.None, memberName, null, new[] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) });
var property = Expression.Dynamic(binder, typeof(object), expression);
var isValid = false;
var right = Expression.Constant(contactValue);
var result = Expression.MakeBinary(ExpressionType.Equal, property, right);
var func = typeof(Func<,>).MakeGenericType(dynamicObj.GetType(), typeof(bool));
var expr = Expression.Lambda(func, result, expression).Compile();
isValid = (bool)expr.DynamicInvoke(dynamicObj);
Run Code Online (Sandbox Code Playgroud) 我有一个LambdaExpression类型为Expression<Func<T, string>>. 代码的设计目前不允许我保留T,这意味着我被迫使用较慢的DynamicInvoke而不是Invoke.
因为我知道T我想要转换表达式的类型,以便它接受一个T对象,允许我使用Invoke. 如何?
这是一个好的开始
class Program
{
class MyClass
{
public string MyProperty => "Foo";
}
static LambdaExpression GetExpression(Expression<Func<MyClass, object>> expr)
{
return expr;
}
static void Main(string[] args)
{
var e1 = GetExpression(t => t.MyProperty);
var e2 = Expression.Lambda<Func<object, object>>(e1, e1.Parameters);
object myClass = new MyClass();
string s1 = (string)e1.Compile().DynamicInvoke(myClass);
object s2 = e2.Compile().Invoke(myClass);
}
}
Run Code Online (Sandbox Code Playgroud) 这是我学习表达式树的教程。
我有超过 35 列要显示,但用户可以选择一次显示 10 列。因此,当用户在搜索框中键入内容时,我只想搜索用户可见的列。
SELECT FirstName, LastName, Address, ..., State
FROM Students
WHERE Id == @Id col1 AND (
FirstName LIKE '%@searchText%' OR
LastName LIKE '%@searchText%' OR
Address LIKE '%@searchText%' OR
...
State LIKE '%@searchText%')
Run Code Online (Sandbox Code Playgroud)
回到 Linq,这就是我试图完成它的方式:
var result = db.Students
.Where(GetPredicate(id, listOfColumns))
.ToList();
Run Code Online (Sandbox Code Playgroud)
这是私有方法:
private Expression<Func<Student, bool>> GetPredicate(int id, List<string> listOfColumns)
{
ParameterExpression pe = Expression.Parameter(typeof(Student), "s");
Expression left0 = Expression.Property(pe, "Id");
Expression right0 = Expression.Constant(id);
Expression e0 = Expression.Equal(left0, right0);
//Here ... omitted code …Run Code Online (Sandbox Code Playgroud) expression-trees ×10
c# ×9
lambda ×5
linq ×3
reflection ×2
c ×1
func ×1
iqueryable ×1
parsing ×1