如何使用动态构建的Lambda表达式创建和填充动态对象 [英] How do I create and populate a dynamic object using a dynamically built lambda expression

查看:536
本文介绍了如何使用动态构建的Lambda表达式创建和填充动态对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I'm trying to create and populate a dynamic object from a dataset that is only known at run time. In the code below, I create my IEnumerable results from my dataset with some known fields (ID, Primary Data, DisplayOrder, IsActive) and one user-define field (Phone Number) which I won't know at design time, and therefore must be built dynamically. The code below works, but only because I've hard-coded the dynamic field Phone Number. How do I build the Lambda expression dynamically to handle those fields only known at runtime. I want the equivalent of

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替换为:

just realized from question that the field source should be dynamic as well. So, in the above code, replace any occurrence of pb.tbList_DataText by:

((IEnumerable<X>)pb.GetType().GetField("tbList_DataText").GetValue(pb))

X应该是ld的类型.但是要小心!这种转换可能会失败.

Where X should be the type of ld. But carefull! This cast can potentially fail.

此外,如果要使用属性而不是字段,只需使用GetProperty而不是GetField.

Also, if you want a property instead of a field, just use GetProperty instead of GetField.

这篇关于如何使用动态构建的Lambda表达式创建和填充动态对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆