从对象属性中获取最大值和名称

Ska*_*der 1 .net c# reflection max

考虑到我有一个带有属性列表的对象,例如

Class Indicators
{
    guid Id
    double? Indocator1;
    double? Indocator1;

    .
    .double? IndocatorP;
}
Run Code Online (Sandbox Code Playgroud)

我想添加一个属性,直接告诉指标名称在所有指标属性中具有最大值。

有什么提示或建议吗?

小智 5

您需要使用反射来获取属性列表并获取值列表,例如,应用MaxLinq 方法:

public class Indicators
{
  public Guid Id { get; set; }
  public double? Indocator1 { get; set; }
  public double? Indocator2 { get; set; }
  public double? Indocator3 { get; set; }

  public (string name, double? value) GetMaxIndicator()
  {
    var pairs = GetType().GetProperties()
                         .Where(p => p.PropertyType == typeof(double?))
                         .Select(p => new
                                      {
                                        name = p.Name,
                                        value = (double?)p.GetValue(this)
                                      });
    string maxName= null;
    double? maxValue = null;
    foreach ( var item in pairs )
      if ( maxValue == null || item.value > maxValue )
      {
        maxName= item.name;
        maxValue = item.value;
      }
    return (maxName, maxValue );
  }
}
Run Code Online (Sandbox Code Playgroud)

测试

static private void Test()
{
  var indicators = new Indicators();
  indicators.Indocator1 = 10;
  indicators.Indocator2 = null;
  indicators.Indocator3 = 20;
  var max = indicators.GetMaxIndicator();
  Console.WriteLine($"{max.name} = {max.value}");
}
Run Code Online (Sandbox Code Playgroud)

输出

Indicator3 = 20
Run Code Online (Sandbox Code Playgroud)

此示例假定成员是可读写的,并且在重复的情况下返回最后找到的成员,但您可以改为返回命名值元组的列表。

您可以将其用于带有GetFields.

您也可以将两者结合起来,并且您可以使用绑定标志过滤所需的成员,例如,如果您需要非公共或静态成员。

改进更清洁、更坚固的设计

List如果指标的数量是固定的,您应该更喜欢使用, 或数组。

实体类

public class Indicator : IComparable
{
  public string Name { get; set; }
  public double? Value { get; set; }
  public Indicator(string name, double? value = null)
  {
    Name = name;
    Value = value;
  }
  int IComparable.CompareTo(object obj)
  {
    var other = obj as Indicator;
    if ( other == null )
      throw new ArgumentException("Object is not an Indicator");
    if ( obj == null ) return 1;
    if ( Value == null && other.Value == null )
      return 0;
    else
    if ( Value == null )
      return -1;
    if ( other.Value == null )
      return 1;
    else
      return Value.Value.CompareTo(other.Value.Value);
  }
}
Run Code Online (Sandbox Code Playgroud)

集合类

public class Indicators
{
  public Guid Id { get; set; }
  public List<Indicator> Items { get; } = new List<Indicator>();
  //or
  public Indicator[] Items { get; } = new Indicator[IndicatorsCount];
}
Run Code Online (Sandbox Code Playgroud)

因此我们可以简单地写:

  var indicators = new Indicators();
  indicators.Items.Add(new Indicator("Indicator1", 10));
  indicators.Items.Add(new Indicator("Indicator2", null));
  indicators.Items.Add(new Indicator("Indicator3", 20));
  var max = indicators.Items.Max();
  Console.WriteLine($"{max.Name} = {max.Value}");
Run Code Online (Sandbox Code Playgroud)

我们可以把它放在类本身中:

public class Indicators
{
  public Guid Id { get; set; }
  public double?[] Items { get; } = new double?[IndicatorsCount];
  public double? MaxValue => Items.Max();
}
Run Code Online (Sandbox Code Playgroud)