【问题标题】:Is it possible to specify an Expression for a single property selector?是否可以为单个属性选择器指定表达式?
【发布时间】:2015-04-02 04:20:02
【问题描述】:

我可以指定一个方法将Expression<Func<Foo, object>> 作为参数,以获取如下所示的 api:

// With a method declaration like this...
public void Foo(Expression<Func<Bar, object>> selector) { .... }

// ...I can invoke the method like this
Foo(b => b.Baz);
Foo(b => new { b.Baz, b.Foo });

但是,我正在编写一个 API,该 API 将受益于能够允许选择单个属性。像这样:

public void Foo(Expression<Func<Bar, ...>> selector) { .... }

// This would be OK.
Foo(b => b.Baz);

// But this would not...
Foo(b => new { b.Baz, b.Foo });

有没有办法表达这种方式来限制这种表达方式?

当然,我总是可以只记录这一点并在运行时检查表达式,但如果可能的话,如果可以避免的话,我更愿意创建一个不会引发 RuntimeExceptions 的 API。

编辑:

我想我可以将方法声明中 Func 的返回值更改为特定类型,从而至少对表达式进行一些限制。但我不想这样做,因为我希望能够在此方法调用中接受几乎任何类型的属性。

【问题讨论】:

  • 你应该编写你的代码,这样即使他们传递了一个表达式,它做的事情不仅仅是投射到一个属性。无论您拥有的任何代码仅在表达式只是属性访问时才有效,都应该重写以降低脆弱性。

标签: c# lambda expression


【解决方案1】:

不,没有办法通过静态检查要求表达式只是表达式属性的属性访问。您只能在运行时执行此类检查。

【讨论】:

  • 太糟糕了:/如果你能表达这样的概念,那就太酷了。我正在尝试编写 DSL,因此尝试“锁定”可以尽可能多地传递什么样的参数似乎是一个更加用户友好的好主意。虽然我想在这种情况下我只需要满足于更少 - 而是编写更多文档。
  • @wasatz As I said earlier,您应该使用表达式编写代码,使其能够工作,即使传递的不是单个属性,如果可能的话(并且它通常是)。
  • 遗憾的是,在这种情况下它没有多大意义。此方法调用最终将被转换为对另一个系统的外部调用,该系统需要选择单个属性。我可以将它复用到多个调用中……但我真的不喜欢那种幕后魔术。虽然我会考虑一两天,看看是否能找到更好的 API 设计。 :)
【解决方案2】:

如果您将特定父对象用于可接受的类型,则以下内容将在编译时强制执行参数

public void Foo<TSource, TTarget>(Expression<Func<TSource, TTarget>> selector)
    where TSource : Bar
    where TTarget : Bar
{ ... }

由于匿名类型派生自 object,这将阻止它们的使用,因为 TSourceTTarget 都必须派生自 Bar

但是,这仅指定源和结果派生自特定类型 - 根据定义,检查表达式是运行时检查,因为您正在验证对象中的数据。

【讨论】:

  • 这将阻止使用匿名类型,但它不会要求表达式只是参数到该参数的属性的投影。它可以包含解析为适当类型的任何内容。除了 OP 在创建此方法时不知道该属性将是什么类型之外,因此他无法首先将其限制为特定类型。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-09-07
  • 1970-01-01
  • 2019-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多