Compile an expression at run time Using Serialize.Linq

I am trying to Serialize and Deserialize Linq queries. I am currently using Serialize.Linq to serialize and deserialize Linq queries via json. For instance:

    public async Task StoreQuery<T>(string queriedTypeName, string queryName, Expression<Func<T, bool>> query, IEnumerable<T> results)
        where T : class, IStorable
    {

        var expressionSerializer = new ExpressionSerializer(new Serialize.Linq.Serializers.JsonSerializer());
        var queryJson = expressionSerializer.SerializeText(query);

        await storage.AddQuery(queriedTypeName + ".queries", queryJson, ...);
        //etc...
    }

I can successfully deserialize the query if I know the type on which the query expression should work:

    public static bool QueryWouldContain<T>(T storable, string queryJson)
        where T : class, IStorable
    {
            var queryStatement = expressionSerializer.DeserializeText(queryJson);
        var expressionType = queryStatement.ToExpressionNode().ToExpression<Func<T,bool>>().Compile();

        var objectBelongsInQueryResults = expressionType.Invoke(obj)
        return objectBelongsInQueryResults;
    }

However, I would like to be able to detect this type at runtime, rather than compiling time in such cases:

    public static async bool QueriesWouldContain<T>(IEnumerable<T> storables, List<string> queryStrings)
        where T : class, IStorable
    {

        foreach (var querystring in queryStrings)
        {
            var expressionSerializer = new ExpressionSerializer(new JsonSerializer());
            var queryStatement = expressionSerializer.DeserializeText(querystring);

            var expression = queryStatement.ToExpressionNode().ToExpression<Func<?, bool>>().Compile();

            foreach (var storable in storables)
            {
                if (isOfTypeMatchingQuery(storable, expression))
                {
                    var result = expression.Invoke(storable);

                    if (result == false)
                    {
                        return false;
                    }
                }
            }
            return true;
        }

Is there a way to get what type works from an expression? and if so, is there a way to convert this expression to Func?

+4
source share
2 answers

ToExpression . , LambdaExpression.

public static async bool QueriesWouldContain<T>(IEnumerable<T> storables, List<string> queryStrings)
    where T : class, IStorable
{

    foreach (var querystring in queryStrings)
    {
        var expressionSerializer = new ExpressionSerializer(new JsonSerializer());
        var queryStatement = expressionSerializer.DeserializeText(querystring);

        var expression = queryStatement.ToExpressionNode().ToExpression();
        if (!(expression is LambdaExpression lambdaExpression))
            continue; // TODO: or throw
        var d = lambdaExpression.Compile();
        foreach (var storable in storables)
        {
            if (isOfTypeMatchingQuery(storable, d))
            {
                var result = (bool)d.Invoke(storable);

                if (result == false)
                {
                    return false;
                }
            }
        }
        return true;
    }
}
+4

, , @esskar :

...
var expressionNode = queryStatement.ToExpressionNode();
var funcType = typeof(Func<,>).MakeGenericType(new Type[] { type, typeof(bool) });
var method = typeof(ExpressionNode).GetMethods().First(meth => meth.GetGenericArguments().Any() && meth.Name == "ToExpression" && meth.GetParameters().Count() == 1);
var methodWithGenerics = method.MakeGenericMethod(funcType);
dynamic expressionUncompiled = methodWithGenerics.Invoke(expressionNode, new object[] { null });
var expression = expressionUncompiled.Compile();

, .

+2

Source: https://habr.com/ru/post/1693219/


All Articles