C #: Как перечислить класс с вложенными классами и со всеми полями

У меня есть один БОЛЬШОЙ .ini файл. e.c:

[Globals]
EdgeDkShadowColor = 188 196 218
EdgeFillColor = 244 244 244

[SysMetrics]
ActiveCaption = 207 214 232
Background = 58 110 165
Btnface = 244 244 244
...

[Button.Checkbox]
AccentColorHint = 250 196 88
Bgtype = imagefile
BorderColorHint = 29 82 129
FillColorHint = 33 161 33
...

[Button.Checkbox(Checkeddisabled)]
TextColor = 161 161 146

[Button.Checkbox(Mixeddisabled)]
TextColor = 161 161 146

[Button.Checkbox(Uncheckeddisabled)]
TextColor = 161 161 146

И я создаю статический класс. Я хочу перечислить строки .ini и установить значение для всех полей из класса Parameters.

Структура класса:

public static class Parameters
{
    public static class Globals
    {
        public static string EdgeDkShadowColor;
        public static string EdgeFillColor;
        ...
    }

    public static class SysMetrics
    {
        public static string ActiveCaption;
        public static string Background;
        public static string Btnface;
        ...
    }

    public static class Button
    {
        public static class Checkbox
        {
            public static string AccentColorHint;
            public static string Bgtype;
            public static string BorderColorHint;
        }

        public static class Checkbox_Checkeddisabled
        {
            public static string TextColor;
        }

        public static class Checkbox_Mixeddisabled
        {
            public static string TextColor;
        }

        public static class Checkbox_Uncheckeddisabled
        {
            public static string TextColor;
        }
        ...

Как я могу правильно перечислить все поля из класса и инициализировать их, чтобы в конечном итоге получить объект:

Parameters.
Globals.
    EdgeDkShadowColor = "188 196 218";
    EdgeFillColor = "244 244 244";
SysMetrics.
    ActiveCaption = "207 214 232"
    Background = "58 110 165"
    Btnface = "244 244 244"
    ...
Button.
    Checkbox.
        AccentColorHint = "250 196 88"
        Bgtype = "imagefile"
        BorderColorHint = "29 82 129"
        ...       etc.

P.S.

  1. Все значения строковые.
  2. '(' в названии заменено на '_'.
  3. Имя параметра может содержать строку «::». Заменяется на «Ext».

ОБНОВЛЕНИЕ

Я нашел первый код этой задачи. Я пытаюсь использовать эту функцию: Основная часть кода

StringReader str = new StringReader(fileAsString);
string line;
Type curType = null;
while ((line = str.ReadLine()) != null)
{
if (string.IsNullOrEmpty(line) | line.StartsWith(";")) continue;
if (line.Contains('['))
{
    line = line[0] + line[1].ToString().ToUpper() + line.Substring(2);
    var listing = typeof(Parameters).GetNestedTypes().ToList();
    string lineS = line.Trim('[').Trim(']').Trim(')').
                        Replace("(", "_").Replace("::", "Ext").Trim();
    var listingOf = listing.Find(tipe => tipe.Name == lineS);
    curType = listingOf;
}
else
{
    if (curType != null)
    {
        FieldInfo found = curType.GetField(splits[0].Trim(')').Replace("(", "_").Trim());
        if (found != null)
            found.SetValue(null, splits[1].Trim());
    }
}
}

Это работа, но только для одного уровня. Это результат работы этого кода:

http://postimg.org/image/5s28m4c8h/


person lasarevs    schedule 06.06.2013    source источник
comment
Вы говорите, что хотите заполнить объект созданного вами класса на основе того, что вы читаете из текстового файла?   -  person jszigeti    schedule 07.06.2013
comment
Вы еще что-нибудь пробовали? Пожалуйста, опубликуйте свою первую попытку и причину ее неудачи.   -  person p.s.w.g    schedule 07.06.2013
comment
@ p.s.w.g первый код опубликован и ждет помощи   -  person lasarevs    schedule 07.06.2013


Ответы (2)


Это звучит как хороший кандидат для размышлений. Обычно вы читаете каждую строку INI-файла, отслеживая глубину на основе '.' разделитель в конфигурации, затем попробуйте найти подходящее свойство для вашего класса на основе глубины ... Если вы это сделаете, заполните его значением. Я недавно сделал что-то подобное с деревом выражений ... Для каждой строки, разделенной знаком '.' получить доступ к свойству или полю с этим именем, а затем попытаться найти следующий в этом свойстве ... Образец кода было бы довольно безумным, но я определенно подходил бы к нему ... Отражение, поскольку шаблон чтобы свойства и вспомогательные свойства вашего класса соответствовали соглашению об именах в INI-файле.

person Haney    schedule 06.06.2013

Найдено решение:

string bytePath = resPath + themesIni;

if (!File.Exists(bytePath))
{
    if (foundRow != null) bytePath = resPath + @"\" + foundRow.ItemArray[1] + @"\" + themesIni;
}
byte[] arr = File.ReadAllBytes(bytePath);
string fileAsString = new UnicodeEncoding().GetString(arr);
StringReader str = new StringReader(fileAsString);
string line;
Type curType = null;
Type parentType = null;
while ((line = str.ReadLine()) != null)
{
    if (string.IsNullOrEmpty(line) | line.StartsWith(";")) continue;
    if (line.Contains('['))
    {
        line = (line[0] + line[1].ToString().ToUpper() + line.Substring(2))
            .Trim('[').Trim(']').Trim(')').Replace("(", "_").Replace("::", "Ext").Trim();
        string[] splitLines = line.Split('.');
        //splitLines[0] = 
        //    (splitLines[0][0] + splitLines[0][1].ToString().ToUpper() + splitLines[0].Substring(2))
        //    .Trim('[').Trim(']').Trim(')').Replace("(", "_").Replace("::", "Ext").Trim();
        //splitLines[1] = 
        //    (splitLines[1][0] + splitLines[1][1].ToString().ToUpper() + splitLines[1].Substring(2))
        //    .Trim('[').Trim(']').Trim(')').Replace("(", "_").Replace("::", "Ext").Trim();
        if (splitLines.Length > 1)
        {
            if (parentType == null)
            {
                parentType = typeof(Parameters).GetNestedTypes().ToList()
                    .Find(tipe => tipe.Name == splitLines[0]);
                List<Type> listing = parentType.GetNestedTypes().ToList();
                curType = listing.Find(tipe => tipe.Name == splitLines[1]);
            }
            else
            {
                List<Type> listing = parentType.GetNestedTypes().ToList();
                curType = listing.Find(tipe => tipe.Name == splitLines[1]);
            }
        }
        else
        {
            parentType = null;
            List<Type> listing = typeof (Parameters).GetNestedTypes().ToList();
            string lineT = line;
            Type listingOf = listing.Find(tipe => tipe.Name == lineT);
            curType = listingOf;
        }
    }
    else
    {
        string[] splits = line.Split('=');
        splits[0] = splits[0].Substring(0, 1).ToUpper() + splits[0].Substring(1);
        if (curType != null)
        {
            FieldInfo found = curType.GetField(splits[0].Trim(')').Replace("(", "_").Trim());
            if (found != null)
                found.SetValue(null, splits[1].Trim());
        }
    }
}
person lasarevs    schedule 07.06.2013