如何将其重构为通用表达式?

时间:2017-04-09 21:39:05

标签: c# expression-trees

如何将此C#代码重构为一个通用GetBy(string property, string search)方法?

public MyModel GetByName(string name)
    {
        return GetAll().SingleOrDefault(d => string.Equals(d.Name, name, StringComparison.OrdinalIgnoreCase));
    }

    public MyModel GetByUrl(string url)
    {
        return GetAll().SingleOrDefault(d => string.Equals(d.Url, url, StringComparison.OrdinalIgnoreCase));
    }

GetAll()会返回MyModel列表,因此这也是一个问题,它不是IQueryable结果。

3 个答案:

答案 0 :(得分:3)

你可以,但它不是保持类型安全的好方法。 或者,您可以这样做:

public MyModel GetBy<T>(Func<MyModel, T> property, T value) where T : IEquatable<T> {
        return GetAll().SingleOrDefault(d => property(d).Equals(value));
    }

GetBy(m => m.Name, "Foo");

或者:

    public MyModel GetBy(Func<MyModel, bool> predicate) {
                return GetAll().SingleOrDefault(predicate);
            }

GetBy(m => m.Name.Equals("Foo", StringComparison.OrdinalIgnoreCase));

答案 1 :(得分:0)

使用Reflection可以后期绑定到所需的属性:

    public MyModel GetBy(string name, string value)
    {
        var getter = typeof(MyModel).GetProperty(name).GetGetMethod();
        return GetAll().SingleOrDefault(d => 
            string.Equals(getter.Invoke(d, null).ToString(), value, StringComparison.OrdinalIgnoreCase));
    }

(以上假设命名属性始终存在且永远不为空)

答案 2 :(得分:-1)

您可以调用现有方法

public MyModel GetBy(string property, string search)
{
    switch (property) {
        case nameof(MyModel.Name):
            return GetByName(search);
        case nameof(MyModel.Url):
            return GetByUrl(search);
        default:
            throw new ArgumentException($"Unsupported property \"{property}\"");
    }
}

当然,你可以内联这两个功能。

但为什么要在GetAll而不是Set<MyModel>上调用它?