Reputation: 8302
Lets say I have a list that contains 1 record:
[
{
"AccountNumber": 1234,
"eDocConfirms": true,
"eDocStatements": true,
"eDocTaxforms": false
}
]
This list is a strongly typed object with these properties:
public int AccountNumber { get; set; }
public bool? eDocConfirms { get; set; }
public bool? eDocStatements { get; set; }
public bool? eDocTaxforms { get; set; }
Using LINQ, I'd like to turn it into a list that looks like this:
[
{
"AccountNumber": 1234,
"EDocumentTypeName ": "Confirms"
},
{
"AccountNumber": 1234,
"EDocumentTypeName": "Statements"
}
]
This new list will a list of a different type:
public class DeliveryPreference
{
public int AccountNumber { get; set; }
public string EDocumentTypeName { get; set; }
}
Note that Taxforms was not included in the new list because it was set to false in the first list.
I know I could easily do this with some loops, but I would prefer using LINQ.
I understand that Stack Overflow prefers that I show what I have tried, but I am having trouble wrapping my brain around this.
Upvotes: 2
Views: 67
Reputation: 404
This is very ugly code, but it works. It should be easy to comprehend. Reflection can be extracted to a new function.
using System;
using System.Linq;
public class Program
{
public class Account {
public int AccountNumber { get; set; }
public bool? eDocConfirms { get; set; }
public bool? eDocStatements { get; set; }
public bool? eDocTaxforms { get; set; }
}
public class DeliveryPreference
{
public int AccountNumber { get; set; }
public string EDocumentTypeName { get; set; }
}
public static void Main()
{
var acc = new Account {
AccountNumber = 10,
eDocConfirms = true,
eDocStatements = false,
eDocTaxforms = true
};
var transformed = acc.GetType()
.GetProperties()
.Where(p => p.PropertyType == typeof(bool?)
&& ((bool?)p.GetValue(acc)).HasValue
&& ((bool?)p.GetValue(acc)).Value)
.Select(p => new DeliveryPreference {
AccountNumber = acc.AccountNumber,
EDocumentTypeName = p.Name.Substring(4)
});
foreach (var t in transformed) {
Console.WriteLine(t.AccountNumber);
Console.WriteLine(t.EDocumentTypeName);
}
}
}
Upvotes: 0
Reputation: 1613
For this case I would use additional function
public static IEnumerable<string> GetTrueProperties(Data t)
{
if (t.eDocConfirms == true) yield return "Confirms";
if (t.eDocStatements == true) yield return "Statements";
if (t.eDocTaxForms == true) yield return "Tax";
}
simply because it is an object and not a dictionary; else you could dynamically select properties which are true(or you could use reflection, but I think it would be too much here, since you have strongly typed object).
then it would look like
var list = new List<Data> {
new Data
{
AccountNumber = 1,
eDocConfirms = true,
eDocStatements = true,
eDocTaxForms = false
}
};
list.SelectMany(item => GetTrueProperties(item).Select(p => new DeliveryPreference
{
AccountNumber = item.AccountNumber,
EDocumentTypeName = p
}));
Upvotes: 5