C
C#16mo ago
DaVinki

❔ ✅ Display all properties of different types without an attribute in a WPF list?

I have a Vehicle object that looks like this:
public class Vehicle
{
[DoNotLogInCsv]
private ILogger? Logger { get; }
[DoNotLogInCsv]
public VehicleProfile Profile { get; }
public DescribedValue<float> Rpm { get; private set; }
public DescribedValue<int> IntakeManifoldAbsolutePressure { get; private set; }
public DescribedValue<float> EngineLoad { get; private set; }
public DescribedValue<int> FuelPressure { get; private set; }
public DescribedValue<float> ThrottlePosition { get; private set; }
public DescribedValue<float> TimingAdvance { get; private set; }
public DescribedValue<float> IntakeAirTemperature { get; private set; }
public DescribedValue<float> ShortTermFuelTrimBank1 { get; private set; }
public DescribedValue<float> LongTermFuelTrimBank1 { get; private set; }
public DescribedValue<int> VehicleSpeed { get; private set; }
public DescribedValue<float> MafAirFlowRate { get; private set; }
public DescribedValue<int> RuntimeSinceEngineStart { get; private set; }
public DescribedValue<float> CommandedAirFuelEquivalencyRatio { get; private set; }
public DescribedValue<int> EngineOilTemperature { get; private set; }
public DescribedValue<float> FuelInjectionTiming { get; private set; }
}
public class Vehicle
{
[DoNotLogInCsv]
private ILogger? Logger { get; }
[DoNotLogInCsv]
public VehicleProfile Profile { get; }
public DescribedValue<float> Rpm { get; private set; }
public DescribedValue<int> IntakeManifoldAbsolutePressure { get; private set; }
public DescribedValue<float> EngineLoad { get; private set; }
public DescribedValue<int> FuelPressure { get; private set; }
public DescribedValue<float> ThrottlePosition { get; private set; }
public DescribedValue<float> TimingAdvance { get; private set; }
public DescribedValue<float> IntakeAirTemperature { get; private set; }
public DescribedValue<float> ShortTermFuelTrimBank1 { get; private set; }
public DescribedValue<float> LongTermFuelTrimBank1 { get; private set; }
public DescribedValue<int> VehicleSpeed { get; private set; }
public DescribedValue<float> MafAirFlowRate { get; private set; }
public DescribedValue<int> RuntimeSinceEngineStart { get; private set; }
public DescribedValue<float> CommandedAirFuelEquivalencyRatio { get; private set; }
public DescribedValue<int> EngineOilTemperature { get; private set; }
public DescribedValue<float> FuelInjectionTiming { get; private set; }
}
A described value is just a string Description and T Value pair object I want to get all of these properties without the CSV logging attribute to be shown in a WPF list. Any ideas on how I can do this? Couldn't come up with anything after a few hours and can't find much online.
3 Replies
Denis
Denis16mo ago
Have you tried reflection 🪞?
DaVinki
DaVinkiOP16mo ago
I did end up using reflection as you suggested with a nongeneric base type first that ended up looking like this:
public record DescribedValue<T> : DescribedValue
where T : new()
{
public T Value { get; set; }
public override object? ObjectValue => Value;

public DescribedValue(string description, T value) : base(description)
{
Value = value;
}

public DescribedValue(string description) : base(description)
{
Value = typeof(T).IsValueType ? default! : new T();
}

public DescribedValue() : this("No description")
{
}

public override string ToString()
{
return $"{Description}: {Value}";
}
}

public abstract record DescribedValue(string Description)
{
public string Description { get; set; } = Description;

public abstract object? ObjectValue { get; }
}
public record DescribedValue<T> : DescribedValue
where T : new()
{
public T Value { get; set; }
public override object? ObjectValue => Value;

public DescribedValue(string description, T value) : base(description)
{
Value = value;
}

public DescribedValue(string description) : base(description)
{
Value = typeof(T).IsValueType ? default! : new T();
}

public DescribedValue() : this("No description")
{
}

public override string ToString()
{
return $"{Description}: {Value}";
}
}

public abstract record DescribedValue(string Description)
{
public string Description { get; set; } = Description;

public abstract object? ObjectValue { get; }
}
The boxing kind of sucks considering this is going to be hot but oh well, not really an issue compared to SerialPort IO speeds which are the main bottleneck. This is where the reflection was:
private List<DescribedValue>? _allObd2Properties;
public IReadOnlyList<DescribedValue> AllObd2Properties
{
get
{

_allObd2Properties ??= typeof(Vehicle)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CustomAttributes.All(a => a.AttributeType != typeof(DoNotLogInCsvAttribute)))
.Select(p => p.GetValue(this))
.Cast<DescribedValue>()
.ToList();

return _allObd2Properties;
}
}
private List<DescribedValue>? _allObd2Properties;
public IReadOnlyList<DescribedValue> AllObd2Properties
{
get
{

_allObd2Properties ??= typeof(Vehicle)
.GetProperties(BindingFlags.Public | BindingFlags.Instance)
.Where(p => p.CustomAttributes.All(a => a.AttributeType != typeof(DoNotLogInCsvAttribute)))
.Select(p => p.GetValue(this))
.Cast<DescribedValue>()
.ToList();

return _allObd2Properties;
}
}
Thank you for the help
Accord
Accord15mo ago
Was this issue resolved? If so, run /close - otherwise I will mark this as stale and this post will be archived until there is new activity.
Want results from more Discord servers?
Add your server