Итерация по свойствам и значениям объекта, возвращенного с помощью запроса linq в доменной модели - PullRequest
38 голосов
/ 15 марта 2012

У меня есть пользовательский объект в реляционной базе данных, который я сопоставил с CLR через модель домена.Таким образом, используя следующее утверждение, я могу извлечь сущность из моей базы данных в память через запрос LINQ для модели предметной области, например так:

var inspection = (from i in dbContext.New_testinspectionExtensionBases
              where i.New_testinspectionId == currentInspection   
              select i).First();                         

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

Я пытался использовать этот подход, но не мог понять, как исправить синтаксис (и я не уверен, чтоGetProperties - правильный метод для использования, GetFields по какой-то причине не возвращал ничего, поэтому я предположил, что это был путь), но это не имеет значения, так как все, что мне нужно, это доступ на чтение к значению;

var inspectionReportFields = inspection.GetType().GetProperties(); 
// I called this inspectionReportfields because the entity properties correspond to 
// form/report fields I'm generating from this data.

foreach (var reportField in inspectionReportFields)
{
    var value = reportField.GetValue();
    Console.WriteLine(reportField.Name);
    Console.WriteLine(value);
}

Есть ли более простой способ получить значение свойства / поля при использовании модели предметной области, такой как EF или openaccess?Если нет, я пойду правильно?И, наконец, если да, как мне исправить синтаксис в объявлении переменной значения?

Вот несколько примеров полей / свойств из кода, сгенерированного моделью предметной области, для справки;

    private int? _new_systemGauges;
    public virtual int? New_systemGauges 
    { 
        get
        {
            return this._new_systemGauges;
        }
        set
        {
            this._new_systemGauges = value;
        }
    }

    private int? _new_systemAlarm ;
    public virtual int? New_systemAlarm 
    { 
        get
        {
            return this._new_systemAlarm;
        }
        set
        {
            this._new_systemAlarm = value;
        }
    }

Ответы [ 3 ]

74 голосов
/ 15 марта 2012

Я предполагаю, что вы пытаетесь определить универсальный способ «сбрасывать» объект, ничего не зная о его структуре.Если так, то вы идете о вещах в правильном направлении.Вы используете отражение (GetType() и соответствующие методы класса Type) для проверки объекта и возврата его информации.

Причина, по которой GetFields() ничего не вернула, состоит в том, что вы, вероятно, не предоставили праваобязательные флаги.В частности, если вы вызываете перегрузку, которая не принимает никаких параметров, вы получаете только поля public;если вам нужны закрытые поля, вам нужно специально их запрашивать.

В вашем случае GetFields(BindingFlags.NonPublic) вернет вам поля _new_systemGauges и _new_systemAlarm, а GetProperties () вернет вам *Свойства 1012 * и New_systemAlarm.

Другой ключевой элемент, который вы пропустили, заключается в том, что возвращаемые вами данные - это метаданные типа ;он определяет структуру class, а не какой-либо конкретный экземпляр.Если вы хотите узнать, каково значение свойства для конкретного экземпляра, вам нужно спросить об этом:

foreach (var prop in obj.GetType().GetProperties())
{
  Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}

Если у вас есть один из PropertyInfo элементов из метаданных типа, вы можетезапросить значение этого свойства в любом экземпляре этого типа.Это не должен быть тот же экземпляр, который вы использовали изначально.Например:

var objs = somelist.Where(x => x.Id == 1);
foreach (var prop in objs.First().GetType().GetProperties())
{
  int x = 0;
  foreach (var obj in objs)
  {        
    if (prop.PropertyType.Name.Equals("Int32"))
    {
      int val = (int)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = 0x{2:x8}", x++, prop.Name, val);
    }
    else if (prop.PropertyType.Name.Equals("Decimal"))
    {
      int val = (decimal)prop.GetValue(obj, null);
      Console.WriteLine("Obj #{0}: {1} = {2:c2}", x++, prop.Name, val);
    }
    else
    {
      Console.WriteLine("Obj #{0}: {1} = '{2}'", x++, prop.Name, prop.GetValue(obj, null));
    }
  }
}

Технически вы должны проверить результат GetIndexParameters, чтобы увидеть, проиндексировано или нет свойство;параметр null в GetValue на самом деле является массивом значений индекса.

Чтобы преобразовать возвращаемое вами значение, вы можете либо использовать typecasts, либо, если вы хотите быть немного более гибким, использовать Convertметоды класса.Разница, например, в том, что, если у вас есть свойство short, GetValue() вернет короткое представление в штучной упаковке, которое вы не сможете затем ввести как int;сначала нужно распаковать его на short.Использование Convert.ToInt32() выполнит все необходимые шаги для получения значения int из любого свойства, которое преобразуется в целое число.

Преобразование между ссылочными типами проще, поскольку вы можетепросто используйте для этого is и as;они работают так же, как и следовало ожидать с «отраженными» значениями свойств.

2 голосов
/ 15 марта 2012

GetProperties действительно правильный метод.

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

var value = reportField.GetValue(inspection, null);

Вам нужно передать экземпляр, из которого выхотите получить значение, так как объект PropertyInfo не привязан к какому-либо конкретному экземпляру класса.


Обратите внимание на соблюдение стандартных правил именования .NET.

Это может привести кследующее:

NewSystemAlarm вместо New_systemAlarm
newSystemAlarm или _newSystemAlarm вместо _new_systemAlarm
NewTestInspectionExtensionBases вместо New_testinspectionExtensionBases
NewTestInspectionId вместоиз New_testinspectionId

0 голосов
/ 15 марта 2012

Если вы используете OpenAccess, у вас всегда есть полная информация о ваших модельных классах в вашем распоряжении. Информация, полученная там, получена из вашего отображения, что означает, что вам не нужно размышлять над вашими классами (без накладных расходов).

Просто просмотрите контекст.Metadata.PersistentTypes для всех ваших данных отображения классов.

...