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

.NET Programming* Entity Framework Core

Avatar of undefined
Last Comment
it_saige

8/22/2022 - Mon
it_saige

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 -Capture.PNG-saige-
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
it_saige

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-
I started with Experts Exchange in 2004 and it's been a mainstay of my professional computing life since. It helped me launch a career as a programmer / Oracle data analyst
William Peck
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
it_saige

THIS SOLUTION ONLY AVAILABLE TO MEMBERS.
View this solution by signing up for a free trial.
Members can start a 7-Day free trial and enjoy unlimited access to the platform.
See Pricing Options
Start Free Trial
GET A PERSONALIZED SOLUTION
Ask your own question & get feedback from real experts
Find out why thousands trust the EE community with their toughest problems.