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

How to refactor this into generic Expression?

如何将此 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 结果。

您可以直接调用现有的方法

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> 上调用它?

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

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

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

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

(以上假定命名的 属性 始终存在并且永远不会为空)