自定义函数替换lambdas Contains,StartsWith和EndsWith

时间:2011-08-23 14:07:54

标签: c# optimization lambda

是否可以创建一个自定义lambda函数,我可以用下面的.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 个答案:

答案 0 :(得分:2)

可能会想要为字符串编写扩展名(注意,对于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 :(得分:1)

您可以将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);
    }
}

然后将您的searcher()方法更改为:

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));
}

答案 2 :(得分:1)

这是使用反射和表达式树的通用方法中的解决方案。你需要的可能有点过分,但它给了我借口表达树的借口。

    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;
    }