user2673195
user2673195

Reputation:

Create runtime predicate with information from Expression<Func<T, object>>

Assuming the following code

private readonly T entity;

public bool HasUnique<T>(Expression<Func<T, object>> property, IEnumerable<T> entities)
{
}

Where property is a property expression of T entity.

How to check if there is any element in entities with the same property value as entity has, while property is resolved from given property expression?

By now, I can get property name and its value from entity

The problem seems to be how to set up and execute at runtime a predicate? Something like

Func<T, bool> predicate = // build a predicate
var isUnique = !entities.Any(predicate);

The usage would be like this

var isUnique = HasUnique<Person>(p => p.Name, people);

Upvotes: 2

Views: 176

Answers (2)

C Bauer
C Bauer

Reputation: 5103

Do you need an Expression<Func<T,object>>? Because it can be achieved with just Func<T,object>.

using System;
using System.Collections.Generic;
using System.Linq;

namespace LinqPlayground
{
    class Program
    {
        public class UniqueChecker<T>
        {
            public bool HasUnique<T>(Func<T, object> property, IEnumerable<T> entities)
            {
                var uniqueDict = new Dictionary<object, bool>();
                foreach (var entity1 in entities)
                {
                    var key = property(entity1);
                    if (uniqueDict.ContainsKey(key))
                    {
                        uniqueDict[key] = false;
                    }
                    else
                    {
                        uniqueDict.Add(key, true);
                    }
                }
                return uniqueDict.Values.All(b => b);
            }
        }

        public class Person
        {
            public string Name { get; set; }
        }

        static void Main(string[] args)
        {
            var people = new List<Person>
            {
                new Person {Name = "Chris"},
                new Person {Name = "Janet"},
                new Person {Name = "John"},
                new Person {Name = "Janet"},
            };

            var checker = new UniqueChecker<Person>();


            Console.WriteLine("Are names unique? {0}",checker.HasUnique(person => person.Name, people));
        }
    }
}

Upvotes: 0

JLRishe
JLRishe

Reputation: 101680

I'm trying to figure out what the word "Unique" has to do with what you described, and your example usage doesn't involve any entity to compare the contents of people to, but I think you're going for something like this?

public static bool HasUnique<T>(this T referenceItem, Func<T, object> property, 
                                IEnumerable<T> entities)
{
    var referenceProperty = property(referenceItem);
    return entities.Any(e => property(e) == referenceProperty);
}

or maybe this:

public static bool HasUnique<T>(this T referenceItem, Func<T, object> property, 
                                IEnumerable<T> entities)
{
    var referenceProperty = property(referenceItem);
    return entities.Any(e => property(e).Equals(referenceProperty));
}

Or even this:

public static bool HasUnique<T, TProp>(this T referenceItem, Func<T, TProp> property, 
                                IEnumerable<T> entities)
{
    var referenceProperty = property(referenceItem);
    return entities.Any(e => property(e).Equals(referenceProperty));
}

Upvotes: 1

Related Questions