如何使用动态构建的 lambda 表达式创建和填充动态对象
How do I create and populate a dynamic object using a dynamically built lambda expression
我正在尝试从仅在 运行 时间已知的数据集中创建和填充动态对象。在下面的代码中,我从我的数据集中创建了我的 IEnumerable 结果,其中包含一些已知字段(ID、主要数据、DisplayOrder、IsActive)和一个我在设计时不知道的用户定义字段(Phone 数字) ,因此必须动态构建。下面的代码有效,但只是因为我硬编码了动态字段 Phone Number。我如何动态构建 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<tbList_Data> 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<string, object>{
["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<string, object>{
{"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<string, object>)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<string, object>)result)["PhoneNumber"]);
}
编辑:刚刚从问题中意识到字段源也应该是动态的。因此,在上面的代码中,将出现的任何 pb.tbList_DataText
替换为:
((IEnumerable<X>)pb.GetType().GetField("tbList_DataText").GetValue(pb))
其中 X
应该是 ld
的类型。但是要小心!此转换可能会失败。
此外,如果您想要 属性 而不是字段,只需使用 GetProperty
而不是 GetField
。
我正在尝试从仅在 运行 时间已知的数据集中创建和填充动态对象。在下面的代码中,我从我的数据集中创建了我的 IEnumerable 结果,其中包含一些已知字段(ID、主要数据、DisplayOrder、IsActive)和一个我在设计时不知道的用户定义字段(Phone 数字) ,因此必须动态构建。下面的代码有效,但只是因为我硬编码了动态字段 Phone Number。我如何动态构建 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<tbList_Data> 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<string, object>{
["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<string, object>{
{"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<string, object>)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<string, object>)result)["PhoneNumber"]);
}
编辑:刚刚从问题中意识到字段源也应该是动态的。因此,在上面的代码中,将出现的任何 pb.tbList_DataText
替换为:
((IEnumerable<X>)pb.GetType().GetField("tbList_DataText").GetValue(pb))
其中 X
应该是 ld
的类型。但是要小心!此转换可能会失败。
此外,如果您想要 属性 而不是字段,只需使用 GetProperty
而不是 GetField
。