Link to home
Start Free TrialLog in
Avatar of Ruffone
Ruffone

asked on

How do I use a method with expression paramiters

How do I use this method providing all the parameters

Public virtual IEnumerable<TEntity> Get(Expression<Func<TEntity, bool>> filter = null, Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> orderBy = null, String includeProperties = "")

Open in new window

Avatar of it_saige
it_saige
Flag of United States of America image

Here is one potential way:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;

namespace EE_Q29131131
{
    class Program
    {
        static IEnumerable<Person> people = (from i in Enumerable.Range(0, 50)
                                             let now = DateTime.Now
                                             select new Person { ID = i, FirstName = $"FirstName{i}", LastName = $"LastName{i}", IsWorking = i % 2 == 0, Start = now.AddDays(-(i*9)), Finish = now.AddDays(-(i*9)).AddHours(8) });
        static void Main(string[] args)
        {
            Console.WriteLine($"First: {people.First()}");
            Console.WriteLine($"Last: {people.Last()}");
            var filtered = people.AsQueryable().Get(p => (p.IsWorking && (p.ID > 35 && p.ID < 40)), p => p.OrderBy(x => x.Start));
            Console.WriteLine($"First: {filtered.First()}");
            Console.WriteLine($"Last: {filtered.Last()}");
            Console.ReadLine();
        }
    }

    class Person
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public bool IsWorking { get; set; }
        public DateTime Start { get; set; }
        public DateTime Finish { get; set; }
        public override string ToString()
        {
            return $"{{ {string.Join(", ", from property in GetType().GetProperties() select $"{property.Name}: {property.GetValueOrValues(this)}")} }}";
        }
    }

    static class Extensions
    {
        public static IEnumerable<T> Get<T>(this IQueryable<T> source, Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null)
        {
            IQueryable<T> results = source;
            if (filter != null)
            {
                results = results.Where(filter);
            }
            return orderBy != null ? orderBy(results) : results;
        }

        public static string GetValueOrValues(this PropertyInfo property, object source)
        {
            var value = property.GetValue(source, null);
            if (value is null)
            {
                return string.Empty;
            }
            else if (property.PropertyType.Equals(typeof(string)) && typeof(IEnumerable<>).IsAssignableFrom(property.PropertyType))
            {
                return $"{{ {string.Join(", ", from item in value as IEnumerable<object> select item)} }}";
            }
            else
            {
                return value.ToString();
            }
        }
    }
}

Open in new window

Which produces the following output -User generated image-saige-
Avatar of Ruffone
Ruffone

ASKER

How would I use Get<T>… in the context of a "GenericRepository" as opposed to an extension method. I mean how do I pass in a "Filter" and "OrderBy"?

I am trying to figure out how to use the bits on this page. https://tinyurl.com/ydca435z
T is what makes it generic.  Regardless of whether it is an extension method or a class method does not matter; e.g. -
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace EE_Q29131131
{
    class Program
    {
        static IEnumerable<Person> people = (from i in Enumerable.Range(0, 50)
                                             let now = DateTime.Now
                                             select new Person { ID = i, FirstName = $"FirstName{i}", LastName = $"LastName{i}", IsWorking = i % 2 == 0, Start = now.AddDays(-(i * 9)), Finish = now.AddDays(-(i * 9)).AddHours(8) });
        static void Main(string[] args)
        {
            Console.WriteLine($"First: {people.First()}");
            Console.WriteLine($"Last: {people.Last()}");
            var filtered = new QueryableReadOnlyRepository<Person>(people.AsQueryable()).Get<Person>(p => (p.IsWorking && (p.ID > 35 && p.ID < 40)), p => p.OrderBy(x => x.Start));
            Console.WriteLine($"First: {filtered.First()}");
            Console.WriteLine($"Last: {filtered.Last()}");
            Console.ReadLine();
        }
    }

    class Person
    {
        public int ID { get; set; }
        public string FirstName { get; set; }
        public string LastName { get; set; }
        public bool IsWorking { get; set; }
        public DateTime Start { get; set; }
        public DateTime Finish { get; set; }
        public override string ToString()
        {
            return $"{{ {string.Join(", ", from property in GetType().GetProperties() select $"{property.Name}: {property.GetValueOrValues(this)}")} }}";
        }
    }

    public interface IReadOnlyRepository
    {
        IEnumerable<T> Get<T>(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null) where T : class;
    }

    public class QueryableReadOnlyRepository<T> : IReadOnlyRepository
    {
        protected readonly IQueryable<T> source;

        public QueryableReadOnlyRepository(IQueryable<T> source)
        {
            this.source = source;
        }

        protected virtual IQueryable<T> GetQueryable<T>(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null) where T : class
        {
            IQueryable<T> query = source as IQueryable<T>;

            if (filter != null)
            {
                query = query.Where(filter);
            }

            if (orderBy != null)
            {
                query = orderBy(query);
            }

            return query;
        }

        public virtual IEnumerable<T> Get<T>(Expression<Func<T, bool>> filter = null, Func<IQueryable<T>, IOrderedQueryable<T>> orderBy = null) where T : class
        {
            return GetQueryable<T>(filter, orderBy);
        }
    }

    static class Extensions
    {
        public static string GetValueOrValues(this PropertyInfo property, object source)
        {
            var value = property.GetValue(source, null);
            if (value is null)
            {
                return string.Empty;
            }
            else if (property.PropertyType.Equals(typeof(string)) && typeof(IEnumerable<>).IsAssignableFrom(property.PropertyType))
            {
                return $"{{ {string.Join(", ", from item in value as IEnumerable<object> select item)} }}";
            }
            else
            {
                return value.ToString();
            }
        }
    }
}

Open in new window

Produces the same output as above.

-saige-
Avatar of Ruffone

ASKER

ok, So the difference with your code and the code in the article is that the type is passed in at the method level and not the class level and I am still struggling with how to use those
ASKER CERTIFIED SOLUTION
Avatar of it_saige
it_saige
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial