2013-08-05 2 views
4

Я создаю каталог локализации и имею конструктивную дилемму. Прямо сейчас в каталоге хранится Dictionary<string, IString> для хранения переводов, где IString может быть двух типов: Singular или Plural. Это упрощенная версия IString:При использовании NotSupportedException это плохо?

public interface IString 
{ 
    void SetSingular(string singular); 

    string GetSingular(params object[] args); 

    void SetPlural(PluralCategory category, string plural); 

    string GetPlural(PluralCategory category, params object[] args); 
} 

Затем, когда я реализую Singular, я бросаю NotSupportedException для множества методов, который пойманные в каталоге, и Plural делает то же самое для особых методов.

public class Singular : IString 
{ 
    // ... 

    public string GetPlural(PluralCategory category, params object[] args) 
    { 
     throw new NotSupportedException(string.Format(
      "Singular strings don't support GetPlural({0}, {1})", 
      category, args)); 
    } 

    public void SetPlural(PluralCategory category, string plural) 
    { 
     throw new NotSupportedException(string.Format(
      "Singular strings don't support SetPlural({0}, {1})", 
      category, plural)); 
    } 
} 

Этой конструкция исходит из требования, что ключи должны быть уникальными для оба сингулярности и множественных, но я чувствую, что реализация не связанные методы и метание NotSupportedException не пахнет хорошо.

Второй дизайн будет хранить Dictionary<string, StringType> для проверки ключей, где StringType является перечислением, а затем два дополнительных словарей Dictionary<string, Singular> и Dictionary<string, Plural>, которые будут использоваться в зависимости от значения StringType. Это делает его немного более сложным, но не нарушает концепцию интерфейса.

Итак, что вы думаете? Является ли моя первая идея плохим использованием NotSupportedException? Должен ли я пойти на второй дизайн или что-то еще?

Edit: более четкое решение, основанное на @dasblinkenlight идее, должен был объединить методы интерфейса, чтобы получить Singular или Plural в один. У Singulars есть только PluralCategory.None, в то время как Plurals никогда не разрешается содержать эту категорию. Это ограничено методами настройки, оставленными вне интерфейса, которые должны быть определены конкретными реализациями (методы настройки не отображаются ниже).

public interface IString 
{ 
    string GetString(PluralCategory category, params object[] args); 
    bool HasCategory(PluralCategory category); 
} 

public class Singular : IString 
{ 
    private string Text; 

    public string GetString(PluralCategory category, params object[] args) 
    { 
     if (category == PluralCategory.None) 
     { 
      if (Text == null || args == null || args.Length == 0) 
      { 
       return Text; 
      } 
      return string.Format(Text, args); 
     } 
     return null; 
    } 

    public bool HasCategory(PluralCategory category) 
    { 
     return category == PluralCategory.None; 
    } 
} 

public class Plural : IString 
{ 
    private Dictionary<PluralCategory, string> Texts = new Dictionary<PluralCategory, string>(); 

    public string GetString(PluralCategory category, params object[] args) 
    { 
     string text; 
     if (Texts.TryGetValue(category, out text)) 
     { 
      if (text == null || args == null || args.Length == 0) 
      { 
       return text; 
      } 
      return string.Format(text, args); 
     } 
     return null; 
    } 

    public bool HasCategory(PluralCategory category) 
    { 
     return Texts.ContainsKey(category); 
    } 
} 
+0

Хм, все в порядке.InvalidOperationException всегда имеет для меня больше смысла. Не давайте * мне * телефонный звонок и спросите меня, почему он не поддерживается. Egad. –

+0

Не забывайте [dual] (http://en.wikipedia.org/wiki/Dual_ (grammatical_number)) – Guillaume

+0

Если вы используете это для локализации, остановитесь сейчас. У тебя уже столько проблем. Вы думали о гендерном? – Stu

ответ

7

Вы правы, это не очень хорошая идея, чтобы бросить NotSupportedException в такой ситуации. Как правило, вы реализуете интерфейс, чтобы обеспечить общий набор операций, который «унифицирует» группу разнородных классов, предоставляющих различные реализации для набора общих операций.

Однако в вашем случае разнородные классы не могут «унифицироваться»: они сохраняют не только свои собственные реализации, но и свои собственные интерфейсы. Когда вы пытаетесь использовать их равномерно, код генерирует исключение. Общий интерфейс не дает вам всего того, что уберет их от object - пользователи должны знать, какой класс стоит за IString перед выполнением вызова, иначе они рискуют увидеть NotSupportedException.

Есть несколько способов решения этой проблемы: один из способов было бы унифицировать единственного и множественного числа методов, возвращая более сложный ответ, чем простой string:

public enum SingularOrPluralCategory { 
    Singular, 
    // The rest of the PluralCategory enum values 
} 
public class StringForm { 
    public string Text {get; private set;} 
    public SingularOrPluralCategory Category {get; private set;} 
} 
public interface IString { 
    // You may want to omit the setter from the interface, adding it to the class instead 
    void SetForm(SingularOrPluralCategory category, string plural); 
    StringForm GetForm(SingularOrPluralCategory category, params object[] args); 
} 

Теперь сингулярный реализация будет возвращать StringForm с Singular значение в Category, в то время как реализация множественного числа вернет StringForm с одной из нескольких категорий множественного числа. Попытка установить множественную категорию в отдельном подклассе IString может все еще быть ошибкой, но вы можете исправить это, перемещая сеттер на класс, что делает невозможным вызов сеттера с категорией в отдельном подклассе IString.

+0

Это выглядит великолепно. Большое вам спасибо, сейчас пытаюсь. :) – moraes

+0

Теперь я использую этот вариант, пропуская «StringForm» и возвращаю строки напрямую. 'IString' имеет единственный метод' string GetString (категория PluralCategory, params object [] args) '. Для реализации «Singular» просто требуется «PluralCategory.None» и в противном случае возвращает null. Больше никаких исключений. Спасибо за трюк. – moraes

Смежные вопросы