Создайте динамический объект из другого объекта, который имеет словарьсвойство с различными парами ключ-значение - PullRequest
0 голосов
/ 04 июня 2019

Я пытаюсь сопоставить свойства существующего объекта, который содержит некоторые статические свойства. Объект также содержит словарь с парами ключ-значение. Эти пары ключ-значение должны динамически добавляться как свойства к новому объекту, который я создаю.

Это настройка для исходного объекта:

public class MyClass
{
    public string PropA { get; set; }
    public string PropB { get; set; }
    public string PropC { get; set; }

    public IDictionary<string, NameValuePair> PropD { get; set; }
}

public class NameValuePair
{
    public string Name { get; set; }
    public string Value { get; set; }
}

Здесь я создаю список объектов:

void Main()
{

    var data = new List<MyClass>
    {
        new MyClass {PropA = "A1", PropB = "B1", PropC = "C1", PropD = new Dictionary<string, NameValuePair>
        {
            { "Code11", new NameValuePair {Name = "PropD11", Value = "V11"}},
            { "Code12", new NameValuePair {Name = "PropD12", Value = "V12"}}
        }},
        new MyClass {PropA = "A2", PropB = "B2", PropC = "C2", PropD = new Dictionary<string, NameValuePair>
        {
            { "Code21", new NameValuePair {Name = "PropD21", Value = "V21"}},
            { "Code22", new NameValuePair {Name = "PropD22", Value = "V22"}},
        }},
        new MyClass {PropA = "A3", PropB = "B3", PropC = "C3", PropD = new Dictionary<string, NameValuePair>
        {
            { "Code12", new NameValuePair {Name = "PropD12", Value = "V31"}},
            { "Code21", new NameValuePair {Name = "PropD21", Value = "V32"}},
        }},
    };
//Extract column names from static properties
    var staticColumns = typeof(MyClass).GetProperties().Where(n => n.PropertyType == typeof(string)).Select(p => p.Name);

//Extract column names from the dictionary
    var dynamicColumns = data.Where(c => c.PropD.Any()).Select(c => c.PropD).SelectMany(c => c.Values.Select(v => v.Name)).Distinct().ToList();

//Combine to get a new list of columns 
    var columns = staticColumns.Union(dynamicColumns);

//Create object using columns

//Copy values from data to construct the new object.    
}

Мне нужна помощь с логикой для создания объекта во время выполнения, который имеет структуру, как показано ниже, и данные правильно отображаются.

PropA    PropB    PropC  PropD11  PropD12  PropD21  PropD22
------------------------------------------------------------
A1       B1       C1     V11      V12       
A2       B2       C2                       V21      V22
A3       B3       C3              V31      V32  

1 Ответ

1 голос
/ 04 июня 2019

Предполагая, что ваши возможные имена свойств являются статическими, вот класс ответа:

public class AnsClass {
    public string PropA { get; set; }
    public string PropB { get; set; }
    public string PropC { get; set; }

    public string PropD11 { get; set; }
    public string PropD12 { get; set; }
    public string PropD21 { get; set; }
    public string PropD22 { get; set; }
}

А вот оператор LINQ для создания их списка:

var ans = data.Select(d => new AnsClass {
                    PropA = d.PropA,
                    PropB = d.PropB,
                    PropC = d.PropC,
                    PropD11 = d.PropD.Values.FirstOrDefault(v => v.Name == "PropD11")?.Value,
                    PropD12 = d.PropD.Values.FirstOrDefault(v => v.Name == "PropD12")?.Value,
                    PropD21 = d.PropD.Values.FirstOrDefault(v => v.Name == "PropD21")?.Value,
                    PropD22 = d.PropD.Values.FirstOrDefault(v => v.Name == "PropD22")?.Value,
                })
                .ToList();

Если члены PropD являются динамическими, вы можете использовать следующее для создания ExpandoObjects, но вам действительно лучше просто использовать MyClass так, как есть - у него уже лучший дизайн для этого.

var ans2 = new List<dynamic>();
foreach (var d in data) {
    dynamic eo = new ExpandoObject();
    eo.PropA = d.PropA;
    eo.PropB = d.PropB;
    eo.PropC = d.PropC;
    var deo = (IDictionary<string,object>)eo;
    foreach (var dp in d.PropD.Values)
        deo.Add(dp.Name, dp.Value);
    ans2.Add(eo);
}
...