Quick actions

cmd+k|ctrl+k

Navigation

Languages

Defunctionalized predicates

Snippet info

Language

Csharp

Visibility

public

Author

rightfold

Created

2016-11-02T09:15:09Z

Updated

2016-11-02T09:37:00Z

using System;
using System.Linq;

public abstract class Predicate {
    public static Func<T, bool> ToFunc<T>(Predicate p) {
        if (p is ConstPredicate) {
            var p_ = p as ConstPredicate;
            return (x) => p_.Value;
        }
        if (p is PropertyPredicate) {
            var p_ = p as PropertyPredicate;
            var property = typeof(T).GetProperty(p_.Name);
            return (x) => (bool)property.GetValue(x);
        }
        if (p is AndPredicate) {
            var p_ = p as AndPredicate;
            var a = ToFunc<T>(p_.A);
            var b = ToFunc<T>(p_.B);
            return (x) => a(x) && b(x);
        }
        throw new Exception("Unsupported predicate type");
    }

    public static string ToSQL(Predicate p) {
        if (p is ConstPredicate) {
            var p_ = p as ConstPredicate;
            return p_.Value ? "true" : "false";
        }
        if (p is PropertyPredicate) {
            var p_ = p as PropertyPredicate;
            return p_.Name;
        }
        if (p is AndPredicate) {
            var p_ = p as AndPredicate;
            return "(" + ToSQL(p_.A) + ") AND (" + ToSQL(p_.B) + ")";
        }
        throw new Exception("Unsupported predicate type");
    }
}

public sealed class ConstPredicate : Predicate {
    public bool Value { get; }

    public ConstPredicate(bool value) {
        Value = value;
    }
}

public sealed class PropertyPredicate : Predicate {
    public string Name { get; }

    public PropertyPredicate(string name) {
        Name = name;
    }
}

public sealed class AndPredicate : Predicate {
    public Predicate A { get; }
    public Predicate B { get; }

    public AndPredicate(Predicate a, Predicate b) {
        A = a;
        B = b;
    }
}

public static class Program {
    public sealed class Person {
        public bool Alive { get; }

        public Person(bool alive) {
            Alive = alive;
        }
    }

    public static void Main() {
        var predicate = new AndPredicate(
            new ConstPredicate(true),
            new PropertyPredicate(nameof(Person.Alive))
        );
        var people = new[] {
            new Person(alive: true),
            new Person(alive: false),
        };
        foreach (var person in people.Where(Predicate.ToFunc<Person>(predicate))) {
            Console.WriteLine(person.Alive);
        }
        Console.WriteLine(Predicate.ToSQL(predicate));
    }
}
INFO