Эффективный способ инициализации полей и / или свойств универсального класса - PullRequest
0 голосов
/ 19 сентября 2011

Я пишу класс ConfigParser, который читает из файла конфигурации, структурированного так:

[Section]
option1 = foo
option2 = 12
option3 = ;
...

Прочитанная информация фактически хранится в словаре <строка, строка>. Чего я хотел бы добиться, так это:

struct ConfigStruct
{
    public string option1;
    public int option2;
    public char option3 { get; set; }
    // Any other _public_ fields or properties
}

ConfigParser Cp = new ConfigParser("path/to/config/file"); // Loads content
ConfigStruct Cs = Cp.CreateInstance<ConfigStruct>("Section");

Console.WriteLine(Cs.option1); // foo
Console.WriteLine(Cs.option2.ToString()); // 12
Console.WriteLine(Cs.option3.ToString()); // ;

Структура (или класс, неважно) ConfigStruct зависит от приложения, и класс ConfigParser не должен ничего знать об этом. По сути, я хочу проанализировать значение из определенной опции и сохранить его в поле / свойстве с тем же именем. Разбор должен выполняться в соответствии с типом поля / свойства.

Я разработал метод заглушки для него:

public T CreateInstance<T>(string Section) where T : new()
{
    // Gets options dictionary from loaded data
    Dictionary<string, string> Options = this.Data[Section];

    T Result = new T();

    Type StructType = Result.GetType();

    foreach (var Field in StructType.GetFields())
    {
        if (!Options.ContainsKey(Field.Name))
            continue;

        Object Value;

        if (Field.FieldType == typeof(bool))
            Value = Boolean.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(int))
            Value = Int32.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(double))
            Value = Double.Parse(Options[Field.Name]);

        else if (Field.FieldType == typeof(string))
            Value = Options[Field.Name];

        else if (Field.FieldType == typeof(char))
            Value = Options[Field.Name][0];

        // Add any ifs if needed

        else { /* Handle unsupported types */ }

        Field.SetValue(Result, Value);
    }

    foreach (var Property in StructType.GetProperties())
    {
         // Do the same thing with public properties
    }

    return Result;
}
  1. Как вы думаете, это правильный подход к проблеме? Или я должен перенести ответственность инициализации структуры на логику приложения вместо класса ConfigParser? Я знаю, что это более эффективно, но, используя рефлексию, я пишу этот метод только один раз, и он работает для каждой структуры.
  2. Должен ли я использовать отражение для вызова Parse (), чтобы я мог избежать всех этих ifs? Или вы предпочитаете делать эти преобразования тип за типом, чтобы предотвратить непредвиденное поведение?

Спасибо за ваше время.

Ответы [ 2 ]

0 голосов
/ 19 сентября 2011

Предполагается, что есть конкретная причина, по которой вы не используете app.config / web.config или другие встроенные файлы конфигурации.

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

  2. Отражение - фантастический инструмент, но с некоторыми накладными расходамитаким образом, если список типов конечен, то указание их вручную более эффективно или, наоборот, отражает только неизвестные типы.Также я бы изменил ваши if блоки на оператор switch, вы получите эффективность, если компилятор IL сможет полностью оптимизировать блок условий.

0 голосов
/ 19 сентября 2011

Я думаю, что есть более простое решение. Вы можете использовать собственный обработчик разделов для хранения ваших настроек, здесь подробно описаны обработчики пользовательских разделов: http://devlicio.us/blogs/derik_whittaker/archive/2006/11/13/app-config-and-custom-configuration-sections.aspx).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...