0

I have a function like this:

public CountryDto FindCountryByName(string name)
{
    Country country = _countryRepository.GetAll().Where(g => g.Name.ToLower().Trim() == name.ToLower().Trim()).FirstOrDefault();

    var dto = _mapper.Map<Country, CountryDto>(country);

    return dto;
}

and it's referred to GetAll-function in the GenericRepository

public IEnumerable<T> GetAll()
{
    return table.ToList();
}

Is it possible creating a function like this (in the GenericRepository)?

public IEnumerable<T> FindByName(string objname, string name)
{
    return table.Where(t => t.GetType(objname) == name);
}

By example

Country country = _countryRepository.FindByName("CountryName", name);

and

AlbumTrack track = _albumtrackRepository.FindByName("SongTitle", songTitle);
user1531040
  • 2,143
  • 6
  • 28
  • 48
  • Your find by name function looks really peculiar already. Wouldn't you want to find by a particular property value instead? So `.Where(t => t.Name == name)` – DavidG Apr 09 '21 at 09:10
  • I have shown two examples. Maybe you understand what I want. – user1531040 Apr 09 '21 at 09:23
  • 3
    OK, so you want to search by a property value. Why not just pass in an expression? e.g. `Find(Expression> filter)` and inside do `table.Where(filter)`? You use it like `repository.Find(x => x.Name == "Foo")` – DavidG Apr 09 '21 at 09:25

1 Answers1

0

I don't remember where I found this function, I'm using it to generate LINQ queries based on given property name, please note that you can change the search function "Equals" to "Contains" or "StartsWith" :

    ///<summary>
    /// Create query that search in given property of class T for matching results with value 
    /// </summary>
    public static IQueryable<T> CreateSearchQuery<T>(IQueryable<T> queryable, string PropertyName, string value) where T : class
    {
        IQueryable<T> query = queryable;

        List<Expression> expressions = new List<Expression>();

        ParameterExpression parameter = Expression.Parameter(typeof(T), "p");
        MethodInfo Equals_Method = typeof(string).GetMethod("Equals", new[] { typeof(string) });
        MethodInfo ToString_Method = typeof(object).GetMethod("ToString");

        //Iterate through all properties Except inherited ones
        foreach (PropertyInfo prop in typeof(T).GetProperties(BindingFlags.DeclaredOnly | BindingFlags.Instance | BindingFlags.Public)
            .Where(x => x.PropertyType == typeof(string) //properties of type string
            || x.Name == PropertyName))
        {

            ConstantExpression value_expression = Expression.Constant(value, typeof(string));
            MemberExpression member_expression = Expression.PropertyOrField(parameter, prop.Name);

            //Combine ToString() and Equals() methods
            MethodCallExpression callChain = Expression.Call(Expression.Call(member_expression, ToString_Method), Equals_Method, value_expression);

            expressions.Add(callChain);
        }

        if (expressions.Count == 0)
            return query;


        Expression or_expression = expressions[0];

        for (int i = 1; i < expressions.Count; i++)
        {
            or_expression = Expression.OrElse(or_expression, expressions[i]);
        }

        Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(or_expression, parameter);

        return query.Where(expression);
    }
Ahmed HM
  • 110
  • 1
  • 9
  • This only works with string properties. It's also easy to break if you pass in a property name that doesn't exist on the type. – DavidG Apr 09 '21 at 10:05
  • You can add more properties types and null check also. – Ahmed HM Apr 09 '21 at 10:32
  • Sure, but what if you wanted to use an `int` or `DateTime` property? What if someone changed the T class? You wouldn't know there was a problem until runtime which makes this dangerous. – DavidG Apr 09 '21 at 10:36
  • Right, instead of passing property name we pass proprtyInfo, this will make the function more accurate – Ahmed HM Apr 09 '21 at 11:11
  • I'll be thankful if you make some changes to this function to eliminate these weaknesses, so i can refactor it on my project – Ahmed HM Apr 09 '21 at 11:19