如何使用动态构建的lambda表达式创建和填充动态对象

我正在尝试从仅在运行时知道的数据集创建和填充动态对象。 在下面的代码中,我使用一些已知字段(ID,主数据,DisplayOrder,IsActive)和一个用户定义字段(电话号码)从我的数据集创建IEnumerable结果,这在设计时我不知道,因此必须动态构建。 下面的代码有效,但仅仅因为我已经对动态字段电话号码进行了硬编码。 如何动态构建Lambda表达式以处理仅在运行时已知的字段。 我想要相当于

string fieldName = 'PhoneNumber = '; string fieldSource = 'pd.tbList_DataText'; string expression = 'pd=>new { ID = pd.ID, PrimaryData=pd.PrimaryData'; expression += fieldName; expression += FieldSource; expression += '.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()})'; var results = primaryData.Select(expression); 

那我该怎么做呢? 谢谢

  // Get base Data IEnumerable primaryData = await _tbList_DataRepository.GetAsync(ld => ld.ListID == listId && (ld.IsActive == includeInactive ? ld.IsActive : true)); // Get Final Results var results = primaryData.Select(pd => new { Id = pd.ID, PrimaryData = pd.PrimaryData, PhoneNumber = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First() }); 

我看到了几个选择。

1)元组

 var results = primaryData.Select(pd => new { Id = pd.ID, PrimaryData = pd.PrimaryData, Extra = Tuple.Create("PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()) }); // How to access: foreach (var result in results) { Console.WriteLine(result.Id); Console.WriteLine(result.PrimaryData); Console.WriteLine(result.Extra.Item1); Console.WriteLine(result.Extra.Item2); } 

2)字典

 // Using C# 6 notation var results = primaryData.Select(pd => new Dictionary{ ["Id"] = pd.ID, ["PrimaryData"] = pd.PrimaryData, ["PhoneNumber"] = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First() }); // Using C# 5 notation var results = primaryData.Select(pd => new Dictionary{ {"Id", pd.ID}, {"PrimaryData", pd.PrimaryData}, {"PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()} }); // How to access: foreach(var result in results) { Console.WriteLine(result["Id"]); Console.WriteLine(result["PrimaryData"]); Console.WriteLine(result["PhoneNumber"]); } 

3)动态

 var results = primaryData.Select(pd => { dynamic result = new System.Dynamic.ExpandoObject(); result.Id = pd.ID; result.PrimaryData = pd.PrimaryData; // Choose one of the following. Since you only "PhoneNumber" at runtime, probably the second one. result.PhoneNumber = pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First(); ((IDictionary)result).Add("PhoneNumber", pd.tbList_DataText.Where(ld => ld.DataRowID == pd.ID && ld.ListColumnID == 1).Select(ld => ld.DataField).DefaultIfEmpty("").First()); return result; }); // How to access: foreach(var result in results) { Console.WriteLine(result.Id); Console.WriteLine(result.PrimaryData); // Both work, independently how you created them Console.WriteLine(result.PhoneNumber); Console.WriteLine(((IDictionary)result)["PhoneNumber"]); } 

编辑:刚从问题中意识到场源也应该是动态的。 因此,在上面的代码中,将pb.tbList_DataText的任何匹配pb.tbList_DataText为:

 ((IEnumerable)pb.GetType().GetField("tbList_DataText").GetValue(pb)) 

其中X应该是ld的类型。 但仔细! 此演员表可能会失败。

此外,如果您想要一个属性而不是一个字段,只需使用GetProperty而不是GetField