Iterate through properties and values of an object returned via a linq query on a domain model

↘锁芯ラ 提交于 2019-12-02 19:02:24

I assume that you're trying to define a general-purpose way to "dump" an object without knowing anything about its structure. If so, then you are going about things the correct way. You use reflection (GetType() and the associated Type class methods) to inspect the object and return its information.

The reason GetFields() didn't return anything is that you likely did not supply the right binding flags. In particular, if you call the overload that doesn't take any parameters, you only get back public fields; if you want private fields you need to ask for them specifically.

In your case, GetFields(BindingFlags.NonPublic) would give you back the _new_systemGauges and _new_systemAlarm fields, while GetProperties() would give you back the New_systemAlarm and New_systemAlarm properties.

The other key element you missed is that the data you are getting back is the type metadata; it defines the structure of the class, and not any particular instance. If you want to know what the value of a property for a specific instance is, you need to ask for that:

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

One you have one of the PropertyInfo elements from the type's metadata, you can ask for that property value on any instance of that type. It doesn't have to be the same instance that you originally used. For example:

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));
    }
  }
}

Technically you should check the result of GetIndexParameters to see if a property is indexed or not; the null parameter to GetValue is actually an array of index values.

To convert the value you get back you can either use typecasts, or if you want to be a bit more flexible, use the Convert class's methods. The difference is, for example, if you have a short property, GetValue() will return a boxed short, which you cannot then typecast as an int; you have to unbox it to a short first. Using Convert.ToInt32() will perform all of the needed steps to get an int value out of any property that is convertible to an integer.

Converting between reference types is easier since you can just use is and as for that; those work just like you'd expect with "reflected" property values.

GetProperties indeed is the correct method.

To get rid of the compiler error, change your code to this:

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

You need to pass the instance from which you want to obtain the value, as a PropertyInfo object is not bound to any specific class instance.


Please consider following the standard .NET naming rules.

This would lead to the following:

NewSystemAlarm instead of New_systemAlarm
newSystemAlarm or _newSystemAlarm instead of _new_systemAlarm
NewTestInspectionExtensionBases instead of New_testinspectionExtensionBases
NewTestInspectionId instead of New_testinspectionId

If you are using OpenAccess you always have the complete information about your model classes at your disposal. The information there is retrieved from your mapping which means that you needn't reflect over your classes (no overhead).

Just browse trough context.Metadata.PersistentTypes for all of your classes mapping information.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!