【问题标题】:Can I accept both a delegate type T and an Expression<T> in the same parameter?我可以在同一个参数中同时接受委托类型 T 和 Expression<T> 吗?
【发布时间】:2010-08-31 18:48:10
【问题描述】:

我正在尝试编写一个帮助类来表示对象上的字段。辅助类需要能够获取给定实例上字段的值,并返回有关它可以通过反射获得的基础属性的元数据。

我希望通过一个实用方法来创建帮助程序类,该方法被调用如下:

public IEnumerable<IFieldInfo<SomeType>> Fields {
  get {
    yield return FieldHelper.GetFieldInfo<SomeType>(t => t.SomeField);
    yield return FieldHelper.GetFieldInfo<SomeType>(t => t.SomeOtherField);
  }
}

IFieldInfo接口看起来有点像这样:

interface IFieldInfo<in T> {
  public string PropertyName {get;}
  public object GetValue(T obj);
}

在我的应用程序的上下文中,Fields 属性将被相当频繁地访问; GetValue() 方法将被相当频繁地调用,但 PropertyName(以及我为清楚起见省略的其他元数据/反射字段)的访问频率将降低。需要实现 Fields 属性的地方很多,有时还需要很多字段,因此调用 GetFieldInfo 的代码要简单明了,这对于代码的清晰性和维护性很重要;复制字段列表或复制参数只是询问它们不同步的错误。

那么,我该如何写GetFieldInfo?如果我这样做:

public static IFieldInfo<T> GetFieldInfo<T>(Func<T, object> getter);

然后我可以通过调用getter(obj) 来简单地实现GetValue(),但我无法访问该名称。

另一方面,如果我这样做:

public static IFieldInfo<T> GetFieldInfo<T>(Expression<Func<T, object>> getter)

然后我可以提取由表达式表示的属性访问的名称,但实现GetValue() 的唯一方法是在表达式上调用Compile(),我认为这对于某些东西来说是一个荒谬的开销编译器本身可以为我编译,特别是因为GetValue()PropertyName 更常用于这些对象。

有没有办法编写我的 GetFieldInfo 辅助函数来获取单个参数并将其解释为表达式树和委托,而无需在运行时将表达式树编译为委托?

【问题讨论】:

  • Compile() 是解决方案。您可以缓存结果,并且总调用次数是静态绑定的。如果以这种方式实施,我怀疑性能是否会成为问题。
  • 总调用次数不是完全静态绑定的;字段可以被多次调用。除非你说 Expression 本身是一个有效的 Dictionary 键?

标签: c# linq c#-4.0 expression-trees


【解决方案1】:

我看不出任何可能的方法。委托和表达式是两种不同的对象类型,只是碰巧看起来很像。这类似于写作:

  MyFunc("10m");

并且将参数同时视为字符串和小数,而不进行任何转换。

最好的办法是调用 Compile() 并缓存结果。我假设您已经计划缓存通过表达式搜索属性名称的结果。

【讨论】:

  • 是的,但是如果您编写了 MyFunc(10),则在参数上调用 ToString() 并以其他形式获取它是微不足道的(资源方面)。如果 Expression.Compile() 同样微不足道,或者有某种方式可以声明“我确定我会想要这个的编译版本,所以提前为我缓存它以使我的 Compile() 方法超快”我会很高兴将表达式作为参数。
  • 就缓存调用 Compile 的结果而言——是的,这有点帮助,除了 Fields 属性本身比 GetValue 更频繁地被调用——也就是说,GetFieldInfo() 方法通常最终会被调用而没有以任何方式使用其结果。
  • @Stuart:关键不在于 ToString() 是否微不足道 --- 关键在于它是否必须完成。 (一定是)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-08-04
  • 2011-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多