0

My project has the following structures:

public struct Money
{
    public CurrencyCodes Currency;
    public decimal Amount;
}

public class Foo
{
    public Money AdultFare { get; set; }
    public Money ChildFare { get; set; }
    public Money BabyFare { get; set; }
    public Money AdultFee { get; set; }
    public Money ChildFee { get; set; }
    public Money BabyFee { get; set; }
    public Money TotalFare { get; set; }
    public Money TotalFee { get; set; }
}

Now I need to convert all Foo monetary fields from one currency to another. What is the best solution design? use reflection? some another idea?

Elton Santana
  • 950
  • 3
  • 11
  • 22
  • 3
    Why didn't you use an `array` or `collection` in the first place? – Luke Vo Jul 07 '15 at 20:49
  • Not make sense in the design! – Elton Santana Jul 07 '15 at 20:51
  • Please explain more details of your scenario. I have never seen this kind of variable list that cannot be solved by collection or array. – Luke Vo Jul 07 '15 at 20:54
  • ok, I'll edit the question. – Elton Santana Jul 07 '15 at 20:56
  • I don't think you want to go the route of reflection. Perhaps you just need a hard coded method to go through all of the properties. To simplify, you could create `FareAndFee` class that has `Money Fare` and `Money Fee`. – MikeH Jul 07 '15 at 21:05
  • 2
    Just a FYI `Money` is a [mutable struct](http://stackoverflow.com/questions/441309/why-are-mutable-structs-evil). You can get yourself in to a lot of trouble that way, are you sure you don't want it to be a class? – Scott Chamberlain Jul 07 '15 at 21:22
  • This was a doubt from the beginning, in fact, the first version was a class that was subsequently refactored into a struct. I will rethink this! TKS! – Elton Santana Jul 07 '15 at 21:30

2 Answers2

3

Instead of V1, V2...V10 create a list:

List<Money> V = new List<Money>();
V.Add (new Money()); //repeat 10 times

Then you can iterate:

foreach (Money m in V)
{
  //Do your conversion
}

Suggestion After Edit

List<Money> AllMoneyFields = new List<Money>();
public Foo()
{
  AllMoneyFields = new List<Money>
    {AdultFare,ChildFare,BabyFare,AdultFee,ChildFee,BabyFee,TotalFare,TotalFee};
}

Then in another "Convert" method you can iterate through AllMoneyFields.

Suggestion 3

If you want to protect for future Money properties use an enum to describe the property:

//Add a field to Money: public MoneyDescription Description;
enum MoneyDescription
{
  AdultFare,
  AdultFee,
  ....
  TotalFee
} 

List<Money> V = new List<Money>();
foreach (MoneyDescription md in Enum.GetValues(typeof(MoneyDescription)))
{
  V.Add(new Money() {Description = md});
}
MikeH
  • 4,242
  • 1
  • 17
  • 32
1

I would suggest making all of those V fields into an array, like so:

public class Foo
{
    public Money[] V { get; set; } // instantiate as "new Money[10]"
}

You could then go through your V array and easily convert each one, like so:

// in class Foo
public void ConvertAllMoney(CurrencyCodes newCurrency)
{
    foreach (Money m in V)
        m = m.ConvertTo(newCurrency);
}

Alternatively, if you don't want to make an array, you could in fact use reflection, as you suggested:

// in class Foo
public void ConvertAllMoney(CurrencyCodes newCurrency)
{
    foreach (var p in typeof(Foo).GetProperties().Where(prop => prop.PropertyType == typeof(Money)))
    {
        Money m = (Money)p.GetValue(this, null);
        p.SetValue(this, m.ConvertTo(newCurrency), null);
    }
}

Edit: You will want to use my second suggestion, Reflection, as your variables are not in the form of a list.

Jashaszun
  • 9,207
  • 3
  • 29
  • 57