【问题标题】:From property name to passing an Expression<Func<T,object>> to a mapping method从属性名称到将 Expression<Func<T,object>> 传递给映射方法
【发布时间】:2014-04-01 13:47:21
【问题描述】:

我一直在与以下问题作斗争。我有一个DataReader 类,简化如下:

public class DataReader
{
    public string SchemeName { get; set; }        
}

然后我有一个继承 Map 方法的 Map 类。

public class DataReaderMap: CsvClassMap<DataReader>
{
   ...
   private void MapPropertyToColumnHeader()
   {
     // do the mapping of column headers in the csv file to the property name on the 
     // DataReader class.

     //This is what I would do in a simple case.
     this.Map(DataReader => DataReader.SchemeName).Name("SName");  
   }
}

我的问题是正确替换行

this.Map(DataReader => DataReader.SchemeName).Name("SName");  

在我的特定情况下更灵活一些,例如

// This code might be wrong but it is as far as I managed to get!
var par = Expression.Parameter(typeof(DataReader));
var memberExpression = Expression.Property(par, "SchemeName");

// lambaExpression is a LambdaExpression not Expression<Func<DataReader, object>>
// THIS LINE DOES NOT COMPILE OF COURSE!
var lambaExpression = Expression.Lambda(memberExpression, par);

var comp = lambaExpression.Compile();  // this is no useful, is it?

// kvPair.Value is "SName" and is read off a mapping file I use
this.Map(lambaExpression).Name(kvPair.Value);

我或多或少地了解什么是 Lamba 表达式以及如何使用表达式树,但我还不精通应用它们。

这里的问题是我不确定如何为 Map 方法提供类型为 lambaExpression 的

Expression<Func<DataReader, obj>>

正如预期的那样。

当我调试时,我看到 lambaExpression 显示为

lambaExpression
{Param_0 => Param_0.SchemeName}
Body: {Param_0.SchemeName}
CanReduce: false
DebugView: ".Lambda #Lambda1<System.Func`2[csvReaderConsole.Readers.DataReader,System.String]>    (csvReaderConsole.Readers.DataReader $var1)\r\n{\r\n    $var1.SchemeName\r\n}"
Name: null
NodeType: Lambda
Parameters: Count = 1
ReturnType: {Name = "String" FullName = "System.String"}
TailCall: false
Type: {Name = "Func`2" FullName = "System.Func`2[[csvReaderConsole.Readers.DataReader,        csvReaderConsole, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null],[System.String, mscorlib, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089]]"}

但我仍然无法理解如何使用它来推导出等价的表达式

DataReader => DataReader.SchemeName

我通常会使用。

【问题讨论】:

  • 能否也显示 Map 方法的声明。不清楚是接受Expression还是Func。
  • var lambaExpression = Expression.Lambda(memberExpression, par); 编译得很好。你遇到了什么错误?
  • 非常感谢德米特里,我明白了。它现在完美运行。换句话说,您不应该从一个 Lamba 表达式 CAST 到另一个,而是可以使用 Lamba 来生成适当的 Expression 类型。有趣的是,当我使用即时窗口比较调用的输出时 Expression.Lambda>(memberExpression, par) 和 Expression.Lambda(memberExpression, par);我得到完全相同的输出。但是它们的类型显然不同。
  • 你明白了。这是两种不同类型的表达式,类型化和非类型化,在某种意义上它类似于 IEnumerable 与 IEnumerable。

标签: c# lambda expression-trees


【解决方案1】:

假设 Map 函数具有签名 string Map(Expression&lt;Func&lt;DataReader, object&gt;&gt; expr),您只需像这样更改 lambda 表达式:

var lambaExpression = Expression.Lambda<Func<DataReader, object>>(memberExpression, par);

不需要编译它,除非Map 接受Func&lt;DataReader, object&gt; 而不是Expression。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多