【问题标题】:Using the logic from one lambda within a second lambda在第二个 lambda 中使用一个 lambda 的逻辑
【发布时间】:2015-07-14 06:13:43
【问题描述】:

我已经查看了有关此问题的其他问题,但我无法弄清楚如何将答案应用于我的特定情况。假设您有几个看起来像这样的模型:

public class Person
{
    public int PersonId { get; set; }
}

public class Business
{
    public int BusinessId { get; set; }
}

我希望能够编写几个不同的通用方法:使用提供的 Lambda 获取模型的方法可能如下所示:

GetWhere(p => p.PersonId == 1)

还有一个使用唯一键获取模型的方法 - 为了使其灵活,我希望能够使用 Lambda 指定唯一键:

GetByUniqueKey(p => p.PersonId, 1)

或者

GetByUniqueKey(b => b.BusinessId, 1)

理想情况下,GetByUniqueKey 只是构建表达式以发送到GetWhere,然后返回 FirstOrDefault() 结果的简写方法。但是这样做的逻辑完全让我无法理解。我想做什么:

public IEnumerable<TModel> GetWhere(Expression<Func<TModel, bool>> whereExpression)
{
    // Get from DB using expression provided
}

public TModel GetByUniqueKey<TUniqueKey>(
         Expression<Func<TModel, TUniqueKey>> uniqueKeyProperty,
         TUniqueKey value)
{
    return GetWhere(m => uniqueKeyProperty(m) == value).FirstOrDefault();
}

所以我想采用uniqueKeyProperty 表达式,以某种方式在提供的参数上调用它以获取属性,然后在whereExpression 表达式中使用该属性。强>

关于重复问题的说明: 我知道这看起来像其他类似问题的重复,但请注意我已经阅读了这些问题,但我无法弄清楚如何将这些答案应用于我的特定用例。

对 cme​​ts 的一些澄清

简单地说,我想做以下事情:

我想获取表达式p =&gt; p.PersonId 和值1,并生成一个类似于p =&gt; p.PersonId == 1whereExpression。 (感谢@Rob)

【问题讨论】:

  • 你不能只做context.Set&lt;TModel&gt;().FirstOrDefault(whereExpression) 吗?
  • 在您的示例中,我需要“whereExpression”来包含第二个 lambda 的结果。另外我认为您使用的是 EF,而我没有。
  • 如果您正在查询数据库,whereExpression 不能有结果 - 它仍然是表达式,因为我们正在将行上的值与某物进行比较(我们还没有) t 加载行)。您能否包含有关如何手动从数据库加载的代码?
  • 您并没有真正解决手头的问题 - 问题是“我可以在第二个 lambda 中使用一个 lambda 的逻辑吗?如果可以,如何?”
  • 我之所以关注它,是因为Can I use the logic of one lambda in a second lambda, and if so, how 的问题真的没有意义。 如何你想使用 lambda? uniqueKeyProperty(m) == value 甚至不会编译,因为它是。当您不展示如何您将使用它时,要回答一个问题是非常困难的。事实上,您甚至可以只写 GetByUniqueKey(p =&gt; p.PersonId == 1) 而不是 GetByUniqueKey(p =&gt; p.PersonId, 1) - 在这种情况下问题很简单,因为它会简单地调用 GetWhere(expr).FirstOrDefault()。

标签: c# .net lambda


【解决方案1】:

您可以从提供的键选择器和值构建一个新表达式,如下所示:

public TModel GetByUniqueKey<TUniqueKey>(
    Expression<Func<TModel, TUniqueKey>> uniqueKeySelector,
    TUniqueKey value)
{
    return GetWhere(Expression.Lambda<Func<TModel,bool>>(
        Expression.MakeBinary(
            ExpressionType.Equal,
            uniqueKeySelector.Body,
            Expression.Constant(value, typeof(TUniqueKey))),
        uniqueKeySelector.Parameters));
}

对于通过 ID 进行查询,我不会使用这种方法。查看Expression class 上的其他静态方法。

【讨论】:

  • 感谢@pmccloghrylaing,我已经采用了这种方法,这样我就可以有一个很好的快捷方法来通过任何类型的唯一标识符获取单个项目,而无需每次都使用 FirstOrDefault 。在我的实际实现中,我还进行了一些检查以保证只找到一个结果。再次感谢,您的解决方案非常完美。
【解决方案2】:

显然您希望实现某种多态性,一种可能性是让PersonBusiness 从同一个基类继承或从同一个接口继承并共享一个Id 属性。你可以定义

public class Identifiable
{
    public int Id { get; set; }
}

并使PersonBusiness继承自in。然后回调

Func<Identifiable,bool> = iIdentifiable => iIdentifiable.Id == 1

可以为两个类的对象调用。但是,必须更改原始类才能使该方法起作用。

【讨论】:

  • 谢谢,这绝对是一种可行的方法,但我提供的代码只是一个示例,具有这种灵活性还有其他用途,所以我仍然希望能够组合这些 lambda,如果可能的话。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-20
  • 2020-11-08
  • 1970-01-01
  • 2015-04-11
  • 2020-11-06
相关资源
最近更新 更多