kk1988
kk1988

Reputation: 51

How can I get specific type of properties of a class?

I have following class.

public class Unit
{
  public string Name { get; set; }
  public double cConvertFromSI { get; set; }
}

public class UnitList
{
  public Unit m  = new Unit() { Name = "meter", cConvertFromSI = 1 };
  public Unit mm = new Unit() { Name = "millimeter", cConvertFromSI = 1000 };
  public Unit in = new Unit() { Name = "inch", cConvertFromSI = 39.3701 };
}

And I want to get all 'Unit' from 'UnitList'.

// I want to do something like

UnitList MyUnitList = new UnitList();

foreach (Unit Unit in MyUnitList)
{
  // do something with each 'Unit'
}

How can I do it?

Upvotes: 0

Views: 57

Answers (2)

Jack T. Spades
Jack T. Spades

Reputation: 1006

You can implement the IEnumerable<Unit> interface.

    public class UnitList : IEnumerable<Unit>
    {
        public Unit m = new Unit() { Name = "meter", cConvertFromSI = 1 };
        public Unit mm = new Unit() { Name = "millimeter", cConvertFromSI = 1000 };
        public Unit in_ = new Unit() { Name = "inch", cConvertFromSI = 39.3701 };

        public IEnumerator<Unit> GetEnumerator()
        {
            yield return m;
            yield return mm;
            yield return in_;
            //...
        }

        System.Collections.IEnumerator System.Collections.IEnumerable.GetEnumerator()
          => GetEnumerator();
    }

That way you can iterate through a UnitList instance with foreach.

foreach ( Unit u in new UnitList() )
{
}

However, it would probably be more reasonable to just use a List or Array property instead.

Upvotes: 3

LLL
LLL

Reputation: 3771

I hope you have a good reason to not just use a List<Unit>, but this would solve getting the properties dynamically.

public class Unit
{
    public string Name { get; set; }
    public double cConvertFromSI { get; set; }

    public override string ToString()
    {
        return $"{Name} {cConvertFromSI}";
    }
}

public class UnitList
{
    public Unit m { get; set; } = new Unit() {Name = "meter", cConvertFromSI = 1};
    public Unit mm { get; set; } = new Unit() {Name = "millimeter", cConvertFromSI = 1000};
    public Unit iN { get; set; } = new Unit() {Name = "inch", cConvertFromSI = 39.3701}; // in is a reserved keyword btw
}

class Program
{
    static void Main(string[] args)
    {
        var unitList = new UnitList();

        var propertyInfos = typeof(UnitList).GetProperties().Where(p => p.PropertyType == typeof(Unit));
        var units = propertyInfos.Select(propertyInfo => (Unit) propertyInfo.GetValue(unitList)).ToList();

        units.ForEach(u => { Console.WriteLine(u.ToString()); });
    }
}

Note that I added {get; set;} at the end of UnitList fields to make them properties.

If you want to keep them as fields then you would need to get the units like this

   var fields = typeof(UnitList).GetFields().Where(p => p.FieldType == typeof(Unit));
   var units = fields.Select(propertyInfo => (Unit) propertyInfo.GetValue(unitList)).ToList();

Upvotes: 2

Related Questions