Как выйти из повторяющихся заявлений? - PullRequest
2 голосов
/ 04 октября 2011

Просматривая некоторый код проекта, над которым я работаю, я наткнулся на довольно здоровенный метод, который делает следующее:

public string DataField(int id, string fieldName)
{
   var data = _dataRepository.Find(id);
   if (data != null)
  {
      if (data.A == null)
      {
        data.A = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return "A";
      }

      if (data.B == null)
      {
        data.B = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return "B";
      }

    // keep going data.C through data.Z  doing the exact same code
  }
}

Очевидно, что 26 операторов if просто для определениясвойство равно нулю, а затем обновить это свойство и выполнить вызов базы данных, вероятно, очень наивно в реализации.Что было бы лучшим способом сделать эту единицу работы?

Ответы [ 6 ]

3 голосов
/ 04 октября 2011

К счастью C # может динамически проверять и назначать членов класса , поэтому одним из вариантов будет создание списка map и итерация по нему.

    public string DataField(int id, string fieldName)
    {
        var data = _dataRepository.Find(id);

        List<string> props = new List<string>();
        props.Add("A");
        props.Add("B");
        props.Add("C");

        if (data != null)
        {
            Type t = typeof(data).GetType();
            foreach (String entry in props) {
                PropertyInfo pi = t.GetProperty(entry);
                if (pi.GetValue(data) == null) {
                    pi.SetValue(data, fieldName);
                    _dataRepository.InsertOrUpdate(data);
                    return entry;
                }
            }
        }
    }
1 голос
/ 04 октября 2011

есть причудливое решение linq для вашей проблемы с использованием рефлексии:

, но, как было сказано ранее: ваша структура данных не очень хорошо продумана для

public String DataField(int id, string fieldName)
{
    var data = new { Z = "test", B="asd"};
    Type p = data.GetType();

    var value = (from System.Reflection.PropertyInfo fi 
                     in p.GetProperties().OrderBy((fi) => fi.Name)
                     where fi.Name.Length == 1 && fi.GetValue(data, null) != null 
                     select fi.Name).FirstOrDefault();
    return value;
}

та тааааааааа, как выполучить свойство, но обновление еще не сделано.

1 голос
/ 04 октября 2011

Вы можете просто перебрать все символы от 'A' до 'Z'.Это становится трудным, потому что вы хотите получить доступ к атрибуту вашего объекта «data» с соответствующим именем, но это должно (насколько я знаю) быть возможным благодаря функции отражения C #.последовательные операторы if все равно не сделают ваш код красивым: P

0 голосов
/ 04 октября 2011
var data = _dataRepository.Find(id);

Если возможно, вы должны использовать другой тип данных без этих 26 свойств. Этот новый DataType должен иметь 1 свойство, а метод Find должен возвращать экземпляр этого нового DataType; тогда вы можете избавиться от 26, если более естественным образом.

Чтобы вернуть «A», «B» ... «Z», вы можете использовать это:

return (char)65; //In this example this si an "A"

И работать с некоторым преобразованием из данных. Значение до числа от 65 до 90 (от А до Я).

0 голосов
/ 04 октября 2011

Поскольку вы всегда устанавливаете поле с самым низким алфавитом первым и возвращаете, вы можете использовать дополнительное поле в вашем классе, которое отслеживает первое доступное поле.Например, это может быть целое число lowest_alphabet_unset, и вы будете обновлять его всякий раз, когда задаете данные. {X}:

Init:

lowest_alphabet_unset = 0;

В DataField:

lowest_alphabet_unset ++;
switch (lowest_alphabet_unset) {

    case 1: 
        /* A is free */
        /* do something */
        return 'A';
    [...]

    case 7:
        /* A through F  taken */
        data.G = fieldName;
        _dataRepository.InsertOrUpdate(data);
        return 'G';
    [...]
}
0 голосов
/ 04 октября 2011

NB - не используйте, если данные являются объектом, а не этой структурой.

, что мне приходит в голову, что, если AZ все одного типа, то вы можете теоретически получить доступпамять непосредственно для проверки ненулевых значений.

start = &data;

for (i = 0; i < 26; i++){
   if ((typeof_elem) *(start + sizeof(elem)*i) != null){
      *(start + sizeof(elem)*i) = fieldName;
      return (char) (65 + i);
   }
}

не проверено, но чтобы дать представление;)

...