'How select derived props in Aggregate function with 2 class
Plz help with System.Linq.Aggregate
I have the following class
public class MainClass
{
public ClassA someProp { get; set; }
public ClassA someProp2 { get; set; }
}
public class ClassA
{
public virtual Type Types => Type.None;
}
public class ClassB:ClassA
{
public override Type Types => Type.Default;
public string FieldName { get; set; }
}
public class ClassC:ClassA
{
public override Type Types => Type.Value;
public int FieldValue { get; set; }
}
And i want to get FieldName if it is filled in ClassB or the value from ClassC if it is also filled for someProp2 and someProp
I understand how to get 1 value
//for get name
IEnumerable<string> values = entities
.Where(x=>x.someProp!=null || x.someProp2!=null)
.SelectMany(mainClass => new[] {mainClass.someProp,mainClass.someProp2 })
.OfType<ClassB>()
.Select(classB => classB.FieldName)
//for get value
IEnumerable<int> values = entities
.Where(x=>x.someProp!=null || x.someProp2!=null)
.SelectMany(mainClass => new[] {mainClass.someProp,mainClass.someProp2 })
.OfType<ClassC>()
.Select(classC => classC.FieldValue)
but I don’t understand how to get 2 values in 1 requests, because there will be type 2 classes ClassB and ClassC
Probably the best way would be through the Aggregate method!
Tell me how to make the conditions for the selection and the Aggregate method itself
Solution 1:[1]
If you want to use .Aggregate() to achieve your goal, I would suggest that you use an overload that lets you define a seed in addition to the accumulator function after flattening the property pairs.
It could be implemented as follows:
IEnumerable<string> values = entities
.SelectMany(ent => new[] { ent.someProp, ent.someProp2 })
.Aggregate(new List<string>(),
( fields, property ) =>
{
if (property is ClassB)
{
fields.Add(((ClassB)property).FieldName);
}
else if (property is ClassC)
{
fields.Add(((ClassC)property).FieldValue.ToString());
}
return fields;
});
Here, our seed is
new List<string>()
and our accumulator function is
( fields, property ) =>
{
// accumulation logic
return fields;
}
, containing the accumulator value parameter fields and element parameter property.
Our seed is the initial value of our accumulator value. For the first property in the flattened property collection (provided by the .SelectMany()), our accumulator value (fields) is therefore an empty list of strings.
For each element (property), field values are extraced based on the property's class type:
- if
propertyis aClassB,FieldNameis extracted and added to our accumulator value. - if
propertyis aClassC,FieldValueis extracted, and its string value is added to our accumulator value. - (if
propertyis neither of those classes, nothing is added tofields).
After conditionally adding a field value to fields, fields is returned from the accumulator function to be used as the accumulator value in the next iteration of the accumulator function (i.e. for the next property in the flattened collection).
For entities given as follows:
List<MainClass> entities = new()
{
new()
{
someProp = new ClassC() { FieldValue = 4 },
someProp2 = new ClassB() { FieldName = "Flower" }
},
new()
{
someProp = new ClassA() { },
someProp2 = new ClassC() { FieldValue = 7 }
}
};
, the resulting values will contain:
4
Flower
7
Example fiddle here.
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 | Astrid E. |
