【问题标题】:How do I create and populate a dynamic object using a dynamically built lambda expression如何使用动态构建的 lambda 表达式创建和填充动态对象
【发布时间】:2017-03-26 04:44:37
【问题描述】:

我正在尝试从仅在运行时知道的数据集中创建和填充动态对象。在下面的代码中,我从我的数据集创建了我的 IEnumerable 结果,其中包含一些已知字段(ID、主数据、DisplayOrder、IsActive)和一个我在设计时不知道的用户定义字段(电话号码),因此必须动态构建。下面的代码有效,但这只是因为我对动态字段电话号码进行了硬编码。如何动态构建 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()
        });

【问题讨论】:

  • 我一直坚持创建动态属性已经有一段时间了,但我想知道这是否有可能......因为我已经尝试了到目前为止。期待看到动态属性部分的答案。
  • 假设您找到了一种方法,您将如何使用results?如果您甚至不知道自己拥有PhoneNumber,您将如何访问它?
  • System.Reflection
  • FieldSource 是否也在运行时检索到?如何确保它是IEnumerable&lt;T&gt;,以便您可以在其上使用.Where()
  • 是 FieldSource 也在运行时检索。

标签: c# linq lambda dynamicobject


【解决方案1】:

我看到了几个选项。

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

【讨论】:

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