我可以在同一参数中同时接受委托类型T和表达式<t>吗?</t>

时间:2010-08-31 18:48:10

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

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

我希望辅助类由一个实用程序方法创建,该方法被调用如下所示:

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

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

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

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

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

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

1 个答案:

答案 0 :(得分:1)

我看不到任何可行的方法。委托和表达式是两种不同的对象类型,恰好相似。它类似于写作:

  MyFunc("10m");

将参数视为字符串和小数而不进行任何转换。

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