0

I'm trying to get the name of item but I'm having to hard code the locale in the select statement. This is my code

private void GetOrder(Root Wix)
    {
        string locale = Wix.restaurant.locale;
        List<Item> menu = Wix.menu.items;
        List<OrderItem> orderItems = Wix.order.orderItems;
        foreach (var orderItem in orderItems)
        {
            string itemId = orderItem.itemId;
            string itemName = (from m in menu  where m.id==itemId select m.title.en_GB).FirstOrDefault();

            int count = orderItem.count;
            string comment = orderItem.comment;
            int price = orderItem.price;
        }

        string orderComment = Wix.order.comment;
        int totalPrice = Wix.order.price;
    }

How can I replace the hard coded "en_GB" in select m.title.en_GB to the locale value returned in the string locale = Wix.restaurant.locale ?

2
  • 4
    Please provide source code of Item class and classes used in it. Commented Feb 19, 2021 at 12:58
  • And you can also remove linq tag from question, it is not related to LINQ. Commented Feb 19, 2021 at 13:31

2 Answers 2

3

You can use reflection:

string itemName = (from m in menu  where m.id==itemId select (string)m.title.GetType().GetProperty(locale).GetValue(m.title)).FirstOrDefault();

This will throw an exception if the class of your title object has no property that has the same name as the content of the string locale. The following variant will make your itemName null if no such property exists:

string itemName = (from m in menu  where m.id==itemId select (string)m.title.GetType().GetProperty(locale)?.GetValue(m.title)).FirstOrDefault();
Sign up to request clarification or add additional context in comments.

2 Comments

Sorry, I'm getting an error; "Object does not match target type." when I use either of the 2 statements above
Sorry, that was a typo. I already updated the answer.
3

Instead of using slow reflection based approach you can introduce interface like this

public interface ILocalizableString
{
    string en_GB { get; }

    string ru_RU { get; }

    //and so on
}

Implement it by your localized strings and introduce extension method

public static class LocalizableStringExtensions
{
    public static string GetString(this ILocalizableString str, string locale)
    {
        if(str == null)
            return null;
        if(locale == "en_GB")
            return str.en_GB;
        if(locale == "ru_RU")
            return str.ru_RU;
        return str.en_GB; //default
     }
  }

Then in your code

  string itemName = (from m in menu  where m.id==itemId select m.title.GetString(locale)).FirstOrDefault();

This can guarantee good performance, and simple way to extended list of supported languages.

2 Comments

I'd suggest using switch expression instead of if - else statements. ` return locale switch { "en_GB" => item.title.en_GB, "ru_RU" => item.title.ru_RU, ... _ => "undefined" }; `
I think switch expressions are too recent to use them in answers, many people can find them unfamiliar, or may be restricted in language version. If/return approach is clear and obvious, and those who want will convert it to switch or whatever they need.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.