Пользовательская функция для замены лямбда-символов Contains, StartsWith и EndsWith - PullRequest
3 голосов
/ 23 августа 2011

Можно ли создать собственную лямбда-функцию, которую я могу заменить вызовами .Contains()/.StartsWith()/EndsWith() ниже?

Если это так, мне не нужно сравнивать строку search здесь, но я могу сделать это в этой пользовательской функции.Это позволит удалить 2/3 кода ниже, если я прав.

... или если у вас есть какие-либо идеи о том, как минимизировать это, я буду рад это услышать!

private void searcher(ref Expression<Func<Party, bool>> predicate, string search, string keyword, string column)
{
    if (search == "contain")
    {
        if (column == "surname") predicate = predicate.And(p => p.surname.Contains(keyword));
        if (column == "lastname") predicate = predicate.And(p => p.lastname.Contains(keyword));
        if (column == "comment") predicate = predicate.And(p => p.comment.Contains(keyword));
        if (column == "position") predicate = predicate.And(p => p.position.Contains(keyword));
    }
    else if (search == "start")
    {
        if (column == "surname") predicate = predicate.And(p => p.surname.StartsWith(keyword));
        if (column == "lastname") predicate = predicate.And(p => p.lastname.StartsWith(keyword));
        if (column == "comment") predicate = predicate.And(p => p.comment.StartsWith(keyword));
        if (column == "position") predicate = predicate.And(p => p.position.StartsWith(keyword));
    }
    else if (search == "end")
    {
        if (column == "surname") predicate = predicate.And(p => p.surname.EndsWith(keyword));
        if (column == "lastname") predicate = predicate.And(p => p.lastname.EndsWith(keyword));
        if (column == "comment") predicate = predicate.And(p => p.comment.EndsWith(keyword));
        if (column == "position") predicate = predicate.And(p => p.position.EndsWith(keyword));
    }
}

Ответы [ 3 ]

2 голосов
/ 23 августа 2011

Может возникнуть соблазн написать расширение для строки (обратите внимание, что было бы еще лучше с перечислением для where):

public static bool Exists(this string str, string where, string what)
{
   if(where == "start") return str.StartsWith(what);
   if(where == "end") return str.EndsWith(what);
   if(where == "contain") return str.Contains(what);
   return false;
}

Тогда ваш код станет немного проще:

private void searcher(ref Expression<Func<Party, bool>> predicate, string search, string keyword, string column)
{
    if (column == "surname") predicate = predicate.And(p => p.surname.Exists(search ,keyword));
    if (column == "lastname") predicate = predicate.And(p => p.lastname.Exists(search ,keyword));
    if (column == "comment") predicate = predicate.And(p => p.comment.Exists(search ,keyword));
    if (column == "position") predicate = predicate.And(p => p.position.Exists(search ,keyword));
}
1 голос
/ 23 августа 2011

Вот решение в общем методе, который использует отражение и дерево выражений. Вероятно, это излишнее, но это дало мне повод возиться с деревом выражения.

    private bool Searcher<T>(T obj, string search, string keyword, string column)
    {
        PropertyInfo property = obj.GetType().GetProperty(column);
        Dictionary<string, string> dict = new Dictionary<string, string>() { { "contain", "Contains" }, { "start", "StartsWith" }, { "end", "EndsWith" } };
        if (property != null && dict.ContainsKey(search) )
        {
            ParameterExpression objExpression = Expression.Parameter(typeof(T), "obj");
            MemberExpression prop = Expression.Property(objExpression, property);
            MethodCallExpression startsWith = Expression.Call(prop, typeof(String).GetMethod(dict[search], new Type[] { typeof(String) }), Expression.Constant(keyword));
            Expression<Func<T, bool>> expression = Expression.Lambda<Func<T, bool>>(startsWith, objExpression);
            var func = expression.Compile();
            return func(obj);
        }
        else
            return false;
    }
1 голос
/ 23 августа 2011

Вы можете заменить search вторым делегатом, как показано ниже:

private void searcher(ref Expression<Func<Party, bool>> predicate, Func<string, string, bool> searchPredicate, string keyword, string column)
{
        if (column == "surname") predicate = predicate.And(p => searchPredicate(p.surname, keyword));
        if (column == "lastname") predicate = predicate.And(p => searchPredicate(p.lastname, keyword));
        if (column == "comment") predicate = predicate.And(p => searchPredicate(p.comment, keyword));
        if (column == "position") predicate = predicate.And(p => searchPredicate(p.position, keyword));
}

Тогда вы можете свободно передавать любой делегат, который вызывает строку и возвращает bool:

searcher(yourFirstPredicate, (s, k) => s.Contains(k), column);

или , если вы действительно хотите использовать слово в качестве ключа для делегата поиска, вы можете определить метод для возврата вашего делегата:

private static Func<string, string, bool> searchSwitcher(string searchType)
{
    switch(searchType)
    {
        case "end":
            return (s, k) => s.EndsWith(k);
        case "start":
            return (s, k) => s.StartsWith(k);
        default:
            return (s, k) => s.Contains(k);
    }
}

Затем измените свойМетод искателя () для:

private void searcher(ref Expression<Func<Party, bool>> predicate, string search, string keyword, string column)
{
    var searchDelegate = searchSwitcher(search);

        if (column == "surname") predicate = predicate.And(p => searchDelegate(p.surname, keyword));
        if (column == "lastname") predicate = predicate.And(p => searchDelegate(p.lastname, keyword));
        if (column == "comment") predicate = predicate.And(p => searchDelegate(p.comment, keyword));
        if (column == "position") predicate = predicate.And(p => searchDelegate(p.position, keyword));
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...