C# 如何使用动态对象作为lambda表达式的输入?

C# 如何使用动态对象作为lambda表达式的输入?,c#,asp.net,dynamic,lambda,expandoobject,C#,Asp.net,Dynamic,Lambda,Expandoobject,我想将表达式存储在数据库中,以便维护规则引擎。表达式的形式如下例所示: Expression<Func<MyTerm, bool>> expression = t => t.MyProperty == SomeValue; 有没有办法将动态对象用作lambda表达式的输入,或者有没有办法为这样的类编写扩展方法,以便返回对象而不是特定类型?我可以像这样编译表达式: public static Func<MyTerm, bool> Compile(stri

我想将表达式存储在数据库中,以便维护规则引擎。表达式的形式如下例所示:

Expression<Func<MyTerm, bool>> expression = t => t.MyProperty == SomeValue;
有没有办法将动态对象用作lambda表达式的输入,或者有没有办法为这样的类编写扩展方法,以便返回对象而不是特定类型?我可以像这样编译表达式:

public static Func<MyTerm, bool> Compile(string body)
{
    ParameterExpression term = Expression.Parameter(typeof(MyTerm), typeof(MyTerm).Name);
    LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { term }, typeof(bool), body);
    return (Func<DynamicTerm, bool>)exp.Compile();
}

static void Main(string[] args)
{
    MyTerm term = new MyTerm();
    term.AddParameter("SomeParameter", "SomeValue");

    Func<MyTerm, bool> IsGreaterThanSomeParameter = Compile("MyTerm.GetString(\"SomeParameter\")== SomeValue);

    bool result = IsGreaterThanSomeParameter(term);

    Console.WriteLine(result);
    Console.ReadLine();
}
公共静态函数编译(字符串体)
{
ParameterExpression term=表达式.参数(typeof(MyTerm),typeof(MyTerm).Name);
LambdaExpression exp=DynamicExpressionParser.ParseLambda(new[]{term},typeof(bool),body);
返回(Func)exp.Compile();
}
静态void Main(字符串[]参数)
{
MyTerm=新的MyTerm();
术语.AddParameter(“SomeParameter”、“SomeValue”);
Func IsGreaterThanSomeParameter=Compile(“MyTerm.GetString(\“SomeParameter\”)==SomeValue);
bool结果=大于某个参数(术语);
控制台写入线(结果);
Console.ReadLine();
}
我想存储独立于特定实现的lambda表达式,因此如果另一个服务试图将这些表达式编译回函数,则语法应该是现成可用的,无需任何变通的getter。
提前感谢。

事实证明,如果对象上有索引器,System.Linq.Dynamic将尝试在找不到匹配属性时调用它

public class DynamicTerm
{
    private readonly Dictionary<string, object> store = new Dictionary<string, object>();

    public void Set(string key, object value) => store[key] = value;
    public object this[string key] => store[key];
}

public static void Main()
{
    string body = "Term.SomeProperty == \"foo\"";
    ParameterExpression termExpr = Expression.Parameter(typeof(DynamicTerm), "Term");
    var exp = DynamicExpressionParser.ParseLambda(new[] { termExpr }, typeof(bool), body);
    var compiled = (Func<DynamicTerm, bool>)exp.Compile();

    var term = new DynamicTerm();
    term.Set("SomeProperty", "foo");

    Console.WriteLine(compiled(term));
}
公共类dynamicertm
{
私有只读字典存储=新建字典();
公共无效集(字符串键,对象值)=>store[key]=value;
公共对象此[字符串键]=>存储[键];
}
公共静态void Main()
{
string body=“Term.SomeProperty==”foo\”;
ParameterExpression termExpr=表达式。参数(typeof(dynamicertm),“Term”);
var exp=DynamicExpressionParser.ParseLambda(新[]{termExpr},typeof(bool),body);
var compiled=(Func)exp.Compile();
var term=新的dynamicertm();
术语集(“SomeProperty”、“foo”);
Console.WriteLine(编译(术语));
}

我找不到返回类型化数据的方法(它将两边都转换为对象):但它可以处理字符串。也许这是一个起点。

我仍然不懂:1)如何在数据库中存储表达式,2)参数集如何与MyTerm关联,3)为什么要尝试使用动态。如果表达式是固定的,它只访问MyTerm上的一组已知属性,因此不需要动态添加p属性,当然?1)它与我所面临的问题没有太大关系。我只是想为应用程序提供上下文。2)ParameterSet是一个ExpandooObject,它使我能够在运行时向类MyTerm添加参数。3)我的表达式是固定的,但不是可能的表达式集。参数可以添加到MyTerm以及exp可以添加与这些参数相关的表达式,但您没有在运行时将属性添加到
MyTerm
。您添加了一个
GetString
方法,该方法碰巧使用
ExpandoObject
作为字典,但您从未调用
GetString
。您没有在任何地方使用
dynamic
。我添加了AddParameter方法。这是我用来在运行时添加参数的方法您仍然没有任何调用
GetString
,并且您仍然没有使用
ExpandoObject
作为
字典之外的任何东西,这是一个很好的开始。但是我想为了让它工作,我需要这样的东西:public,不是吗[字符串键]{get{/*返回泛型类型T.*/}事实上,我找不到一种方法来做到这一点。你是如何使用你的
DynamicTerm
——你只是关闭它访问属性并进行二进制比较吗?还是做一些更复杂的事情?一个选择是做我回答中的事情,然后使用
ExpressionVisitor
来打开
术语。SomeProperty==(object)“foo”“
转换为
(string)Term.SomeProperty==”foo“
实际上,我只是使用Dynamicerm作为参数的包装,以便进行一些简单的检查。问题是,我希望能够在连接的表达式中使用多个参数。类似于(t.Age>=10 | | t.Name==”Tom“)你的动态字符M在哪里?啊,是的。对不起,我一直把名字弄错了。
public static Func<MyTerm, bool> Compile(string body)
{
    ParameterExpression term = Expression.Parameter(typeof(MyTerm), typeof(MyTerm).Name);
    LambdaExpression exp = DynamicExpressionParser.ParseLambda(new[] { term }, typeof(bool), body);
    return (Func<DynamicTerm, bool>)exp.Compile();
}

static void Main(string[] args)
{
    MyTerm term = new MyTerm();
    term.AddParameter("SomeParameter", "SomeValue");

    Func<MyTerm, bool> IsGreaterThanSomeParameter = Compile("MyTerm.GetString(\"SomeParameter\")== SomeValue);

    bool result = IsGreaterThanSomeParameter(term);

    Console.WriteLine(result);
    Console.ReadLine();
}
public class DynamicTerm
{
    private readonly Dictionary<string, object> store = new Dictionary<string, object>();

    public void Set(string key, object value) => store[key] = value;
    public object this[string key] => store[key];
}

public static void Main()
{
    string body = "Term.SomeProperty == \"foo\"";
    ParameterExpression termExpr = Expression.Parameter(typeof(DynamicTerm), "Term");
    var exp = DynamicExpressionParser.ParseLambda(new[] { termExpr }, typeof(bool), body);
    var compiled = (Func<DynamicTerm, bool>)exp.Compile();

    var term = new DynamicTerm();
    term.Set("SomeProperty", "foo");

    Console.WriteLine(compiled(term));
}