简体   繁体   English

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

[英]How to work with dynamic objects as input for lambda expressions?

I want to store expression in a database in order to maintain a rule engine.我想将表达式存储在数据库中以维护规则引擎。 The expressions are in the form of this example:表达式采用此示例的形式:

Expression<Func<MyTerm, bool>> expression = t => t.MyProperty == SomeValue;

The problem I am facing is that I have to create MyTerm at runtime.我面临的问题是我必须在运行时创建 MyTerm。 In order to still be able to use MyTerm as a parameter for a lambda expression, I implemented a solution with ExpandoObject, like so:为了仍然能够使用 MyTerm 作为 lambda 表达式的参数,我使用 ExpandoObject 实现了一个解决方案,如下所示:

public class MyTerm
{
    ExpandoObject ParameterSet;

    public void AddParameter(string name, object value)
    {
        IDictionary<string, object> dictionary = ParameterSet as IDictionary<string, object>;
        if (dictionary.ContainsKey(name))
        {
            dictionary[name] = value;
        }
        else
        {
            dictionary.Add(name, value);
        }
    }

    public string GetString(string name)
    {
        IDictionary<string, object> dictionary = ParameterSet as IDictionary<string, object>;
        if (dictionary.ContainsKey(name))
        {
            return (string)dictionary[name];
        }
        throw new KeyNotFoundException("Term does not contain parameter {name}.");
    }

The thing is, I gain the advantage of being able to add parameters at runtime to MyTerm, but I have to specify the return type for each getter, instead of being able to use the syntax above:问题是,我获得了能够在运行时向 MyTerm 添加参数的优势,但是我必须为每个 getter 指定返回类型,而不是能够使用上面的语法:

t.MyProperty

Is there a way to use dynamic objects as input for lambda expressions or are there ways to write an extension method for classes like this in order to return an object and not a specific type?有没有办法使用动态对象作为 lambda 表达式的输入,或者有没有办法为这样的类编写扩展方法以返回 object 而不是特定类型? I am able to compile expressions like so:我能够像这样编译表达式:

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();
}

I want to store lambda expressions that are independent from a specific implementation, so if another service tries to compile these expressions back to a function, the syntax should be usable out of the box.我想存储独立于特定实现的 lambda 表达式,因此如果另一个服务尝试将这些表达式编译回 function,则该语法应该开箱即用。 Without any workaroung getters.没有任何工作方法的吸气剂。 Thank you in advance.先感谢您。

It turns out that if your object has an indexer on it, System.Linq.Dynamic will try and call it if it doesn't find a matching property.事实证明,如果您的 object 上有一个索引器,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));
}

I can't find a way of returning typed data (it converts both sides to object): it works with strings however.我找不到返回类型数据的方法(它将双方都转换为对象):但是它适用于字符串。 Perhaps it's a starting point.也许这是一个起点。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM