Как создать MemberExpression для списка <string>, для выражения> - PullRequest
0 голосов
/ 04 октября 2018

Ниже приведен мой код для получения Expression<Func<T,bool>>, который помогает в предоставлении Func<T,bool> для фильтрации списка, теперь для этого мне нужно создать MemberExpression следующим образом (в коде):

 MemberExpression memberExpressionColumn = Expression.Property(parameterType,"X");

Где X - это имя свойства, предназначенного для фильтрации, поэтому, когда я применяю его к List<Person>, легко заменить X на свойство Name, , но когда яиспользуйте List<string> в качестве источника, затем как создать MemberExpression, что приводит к исключению

void Main()
{
    List<Person> personList = new List<Person>()
        {
            new Person{ Name = "Shekhar", Age = 31},
            new Person{ Name = "Sandip", Age = 32},
            new Person{ Name = "Pramod", Age = 32},
            new Person{ Name = "Kunal", Age = 33}
        };


    var personNameList = personList.Select(p => p.Name).ToList();

    var personNameHashset = new HashSet<string>(personNameList);

    var nameList = new List<string>() { "Kunal", "Pramod", "Mrinal" };

    var finalExpression = personNameHashset.EqualExpression<string>("Name");

    var finalFunc = finalExpression.Compile();

    var result = nameList.Where(finalFunc);

    result.Dump();
}

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

public static class ExpressionTreesExtension
{
    public static Expression<Func<T, bool>> EqualExpression<T>(this HashSet<string> nameHashSet, string columnName)
    {
        var expressionList = new List<Expression>();

        ParameterExpression parameterType = Expression.Parameter(typeof(T), "obj");

        // Exception Here - How to create MemberExpression for primitive type list List<string>

        MemberExpression memberExpressionColumn = Expression.Property(parameterType,columnName);

        var containsMethodInfo = typeof(StringListExtensions).GetMethod("Contains", new[] { typeof(string), typeof(HashSet<string>) });

        ConstantExpression constant = Expression.Constant(nameHashSet, typeof(HashSet<string>));

        var resultExpression = Expression.Call(null, containsMethodInfo, memberExpressionColumn, constant);

        return Expression.Lambda<Func<T, bool>>(resultExpression, parameterType);
    }
}

public static class StringListExtensions
{
    /// <summary>
    /// String Extension - Contains (Substring)
    /// </summary>
    /// <param name="source"></param>
    /// <param name="subString"></param>
    /// <returns></returns>
    public static bool Contains(this string name, HashSet<string> nameHashSet)
    {
        return nameHashSet.Contains(name);
    }
}

1 Ответ

0 голосов
/ 04 октября 2018

Как я понимаю, вам нужно получить такой результат:

var result = nameList.Where(obj => personNameHashset.Contains(obj));

Поскольку вам не нужно получать свойство Name из строки, вы не должны использовать memberExpressionColumn, и вы можете вызватьcontainsMethodInfo с ParameterExpression parameterType.Вы можете упростить свой метод, чтобы получить Expression<Func<T, bool>> вот так

public static Expression<Func<T, bool>> EqualExpression<T>(this HashSet<string> nameHashSet)
{
    ParameterExpression parameterType = Expression.Parameter(typeof(T), "obj");
    var containsMethodInfo = typeof(StringListExtensions).GetMethod("Contains", new[] { typeof(string), typeof(HashSet<string>) });
    ConstantExpression constant = Expression.Constant(nameHashSet, typeof(HashSet<string>));
    var resultExpression = Expression.Call(null, containsMethodInfo, parameterType, constant);
    return Expression.Lambda<Func<T, bool>>(resultExpression, parameterType);
}

и вызвать его:

var finalExpression = personNameHashset.EqualExpression<string>();
var finalFunc = finalExpression.Compile();
var result = nameList.Where(finalFunc);
...