Parse a Lambda in C#

1k views Asked by At

I want to convert a string containing an expression of a known signature Func<dynamic, bool) into a dynamic function I can call.

(x) => x.Age > 18  //Typecastable to Func<dynamic, bool>

var function = (Func<dynamic, bool>) Lamdba.Parse("(x) => x.Age > 18")

I'm looking for the equivalent of Lambda.Parse

Full code of what I'm trying to achieve below:

using System;
using System.Dynamic;
using System.Collections.Generic;

public class DynamicModelTests
{
    public static void Main()
    {
        //Illustration purpose... Working code
        dynamic model = new ExpandoObject();
        model.Age = 18;
        Func<dynamic, bool> isAdultRule = (x) => x.Age >= 18;
        IDictionary<string, object> dict = model;
        dict["IsAdult"] = (Func<bool>) (() => isAdultRule(model));
        Console.WriteLine($"Is Adult: {model.IsAdult()}");
        //Working code ends

        //Pseudo code starts... Pseudo only because it needs a working Lambda.Parse()
        Compose(model, "IsAdult",  "(x) => x.Age >= 18");
        Compose(model, "CanWatchRRated", "(x) => x.IsAdult()");
        bool isAdult = model.CanWatchRRated();
        bool result = ExecuteByName(model, "CanWatchRRated");
        Console.WriteLine($"Is Adult #2: {isAdult}");
        Console.WriteLine($"Same as Is Adult #2: {result}");
        //ends
    }

    public static void Compose(dynamic model, string ruleName, string expression)
    {
        var method = GetMethod(model, expression);
        var ruleCallExpression = $"() => method(model)";

        IDictionary<string, object> dict = model;
        dict[ruleName] = (Action) method;
    }

    public static Func<dynamic, T> GetMethod<T>(dynamic model, string expression)
    {
        return Lambda.Parse<dynamic, T>(expression); 
    }

    public static T Execute<T>(dynamic model, string expression)
    {
        return GetMethod(model, expression)(model);
    }

    //Should be called after compose... otherwise, throws MethodNotFound Exception
    public static T ExecuteByName<T>(dynamic model, string ruleName)
    {
        IDictionary<string, object> dictionary = model;
        if(!model.ContainsKey(ruleName))
        {
            throw new MethodNotFoundException();
        }

        return (T) model.Invoke(ruleName);

    }
}

public class MethodNotFoundException : Exception
{
}

Is there a ready-made Lambda.Parse() that I can use?

Note #1: The model must be of type 'dynamic'. I'm using Rick Strahl's libary instead of rolling my own DynamicObject implementation

Note #2: All the examples of System.Linq.Dynamic.DynamicExpression to parse expressions only seem to work with known types. They didn't work for me with type 'dynamic'. If it does for you I'm all ears.

Thanks!

0

There are 0 answers