2012-11-21 4 views
0

У меня есть словарь CParam Регистр как ключ,имени переменного в строку

CParam имеет одно поле, которое считывается из внешнего текстового файла и описание используется в качестве ключа для чтения в HumanDesc.

Текстовый файл - это файл перевода, а описание должно быть строкой. Нечто подобное

PLACE_HOLDER1 "First Place where things are put" 
PLACE_HOLDER2 "Secod Place where things are put" 
..... 

Я могу легко сделать это путем вставки регистра, как и поместив его в кавычки. Но есть 100 регистров, и это было бы утомительно (и не очень элегантно). Есть ли способ, с помощью которого конструктор может справиться с этим для меня.

Ниже приведен очень упрощенный пример того, что я ма пытаюсь сделать:

using System; 
using System.Collections.Generic; 
namespace Var2String 
{ 
    public class CParam 
    { 
    public ushort Register; 
    public string Description; 
    public ushort Content; 
    public string HumanDesc; 
    public CParam(ushort t_Register, string t_Description, string t_HumanDesc, ushort DefaultVal) 
    { 
     Register = t_Register; 
     Description = t_Description; 
     Content = DefaultVal; 
     HumanDesc = t_HumanDesc; 
    } 
}; 

static class Device1 
{ 
    public const ushort PLACE_HOLDER1 = 0x0123; 
    public const ushort PLACE_HOLDER2 = 0x0125; 
    public const ushort PLACE_HOLDER_SAME_AS_1 = 0x0123; 
    public static Dictionary<ushort, CParam> Registers; 
    static Device1() 
    { 
     Registers = new Dictionary<ushort, CParam>() 
    { 
     {PLACE_HOLDER1, new CParam(PLACE_HOLDER1,"PLACE_HOLDER1","Place One Holder",100)}, 
     {PLACE_HOLDER2, new CParam(PLACE_HOLDER1,"PLACE_HOLDER2","Place Two Holder",200)} 
    }; 
     /* 
     * Like to be able to do this 
     * And constructor CParam 
      Registers = new Dictionary<ushort, CParam>() 
    { 
     {PLACE_HOLDER1, new CParam(PLACE_HOLDER1,"Place One Holder",100)}, 
     {PLACE_HOLDER2, new CParam(PLACE_HOLDER1,"Place Two Holder",200)} 
    }; 
     */ 
    } 

} 
class Program 
{ 
    static private string LookUpTranslationFor(string Key) 
    { 
     string Translated = "Could not find Val for " + Key; 
     //This would read XML file use Key to get translation 
     return Translated; 
    } 
    static void Main(string[] args) 
    { 
     Console.WriteLine(Device1.Registers[Device1.PLACE_HOLDER1].HumanDesc); 
     Console.WriteLine(Device1.Registers[Device1.PLACE_HOLDER2].HumanDesc); 
     Device1.Registers[Device1.PLACE_HOLDER2].HumanDesc = LookUpTranslationFor(Device1.Registers[Device1.PLACE_HOLDER2].Description); 
     Console.WriteLine(Device1.Registers[Device1.PLACE_HOLDER2].HumanDesc); 
     Console.ReadKey(true); 
    } 
} 

}

ответ

2

Я не уверен, что я правильно Вас понял, но если вы зарегистрируетесь переменные не константные вы можете сделать что-то вроде этого:

1.Add другой конструктор CParam

public class CParam 
{ 
    .... 

    public CParam(Expression<Func<ushort>> ex, string t_HumanDesc, ushort DefaultVal) 
    { 
     Content = DefaultVal; 
     HumanDesc = t_HumanDesc; 
     Description = ((MemberExpression) ex.Body).Member.Name; 
     Register = ex.Compile().Invoke(); 
    } 
}; 

2. Измените класс вашего устройства следующим образом:

internal static class Device1 
{ 
    public static ushort PLACE_HOLDER1 = 0x0123; 
    public static ushort PLACE_HOLDER2 = 0x0125; 
    public static ushort PLACE_HOLDER_SAME_AS_1 = 0x0123; 
    public static Dictionary<ushort, CParam> Registers; 

    static Device1() 
    { 
     Registers = new Dictionary<ushort, CParam>() 
         { 
          {PLACE_HOLDER1, new CParam(() => PLACE_HOLDER1, "Place One Holder", 100)}, 
          {PLACE_HOLDER2, new CParam(() => PLACE_HOLDER1, "Place Two Holder", 200)} 
         }; 
    } 
} 

Обратите внимание, что это не будет работать с переменными const!

+0

Да, это сделало бы это. Раньше я смотрел на Exression, я пытался избежать использования Linq, и PLACE_HOLDERS1 не может быть изменен. Но в противном случае это сработает, и я буду использовать его, если не найду другого решения. –

+0

Вы можете сделать PLACE_HOLDER1 readonly, чтобы никто не мог его изменить. – HoberMellow

+0

Я не могу использовать readonly в операторах case, и случай используется во многих местах существующего кода. –

0

Чтобы получить имя переменной вам нужно использовать класс Reflection, но вы не можете использовать отражение на типы значений

0

Вы можете создать класс, содержащий требуемые свойства, с помощью Reflection.Emit, но для меня это кажется хакированным, и вам не хватит IntelliSense, поскольку члены будут созданы во время выполнения (вызывая те же проблемы, что и у вас, используя строки).

Если структура файла является твердой и от нее зависит, почему бы не создать небольшую утилиту, которая генерирует файл класса из файла конфигурации? Затем вы можете использовать класс в качестве заполнителя, заполняя элементы данными из файла конфигурации во время выполнения (используя Reflection для отображения свойств класса из свойств в файл) или напрямую установите данные в классе.

Затем вы можете добавить этот класс конфигурации в свой проект и при необходимости преобразовать его в словарь.

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