C# 遍历通过域模型上的 linq 查询返回的对象的属性和值
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/9724247/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Iterate through properties and values of an object returned via a linq query on a domain model
提问by bdemartino
I have a custom entity in a relational database that I have mapped to the CLR via a domain model. So by using the following statement, I can pull in an entity from my database into memory via a LINQ query on the domain model, like so;
我在关系数据库中有一个自定义实体,我已通过域模型将其映射到 CLR。因此,通过使用以下语句,我可以通过域模型上的 LINQ 查询将数据库中的实体拉入内存,如下所示;
var inspection = (from i in dbContext.New_testinspectionExtensionBases
where i.New_testinspectionId == currentInspection
select i).First();
There are properties/fields on this entity that I need access to, I need to be able to determine the property/field name as well as it's value. I want to loop through these items in memory, and write out their names and values to the console.
我需要访问此实体上的属性/字段,我需要能够确定属性/字段名称及其值。我想在内存中遍历这些项目,并将它们的名称和值写出到控制台。
I tried using this approach, but couldn't figure out how to correct the syntax (Nor am I sure that GetProperties is the correct method to use, GetFields wasn't returning anything for some reason so I assumed this was the way to go) but it doesn't really matter since all i need is read access to the value;
我尝试使用这种方法,但无法弄清楚如何更正语法(我也不确定 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);
}
Is there an easier way to get the property/field value when utilizing a domain model like EF or openaccess? If not, am I going about it the right way? And lastly, if so, how do I fix the syntax in the value variable declaration?
在使用 EF 或 openaccess 等域模型时,是否有更简单的方法来获取属性/字段值?如果没有,我会以正确的方式进行吗?最后,如果是这样,我如何修复值变量声明中的语法?
Here are some sample fields/properties from the code generated by the domain model, for reference;
以下是域模型生成的代码中的一些示例字段/属性,以供参考;
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;
}
}
采纳答案by Michael Edenfield
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 Typeclass methods) to inspect the object and return its information.
我假设您正在尝试定义一种通用的方法来“转储”一个对象而不知道它的结构。如果是这样,那么您正在以正确的方式处理事情。您可以使用反射(GetType()以及相关Type类的方法)检查的对象,并返回其信息。
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 publicfields; if you want private fields you need to ask for them specifically.
之所以GetFields()没有返回任何东西是,你可能没有提供正确的绑定标志。特别是,如果你调用不带任何参数的重载,你只会得到public字段;如果您想要私有字段,则需要专门询问它们。
In your case, GetFields(BindingFlags.NonPublic)would give you back the _new_systemGaugesand _new_systemAlarmfields, while GetProperties() would give you back the New_systemAlarmand New_systemAlarmproperties.
在您的情况下,GetFields(BindingFlags.NonPublic)会给您_new_systemGauges和_new_systemAlarm字段,而 GetProperties() 会给您New_systemAlarm和New_systemAlarm属性。
The other key element you missed is that the data you are getting back is the typemetadata; 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:
您错过的另一个关键要素是您返回的数据是类型元数据;它定义了 的结构class,而不是任何特定实例。如果您想知道特定实例的属性值是多少,您需要询问:
foreach (var prop in obj.GetType().GetProperties())
{
Console.WriteLine("{0} = {1}", prop.Name, prop.GetValue(obj, null));
}
One you have one of the PropertyInfoelements 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:
如果您拥有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));
}
}
}
Technically you should check the result of GetIndexParametersto see if a property is indexed or not; the nullparameter to GetValueis actually an array of index values.
从技术上讲,您应该检查结果GetIndexParameters以查看属性是否已编入索引;nullto的参数GetValue实际上是一个索引值数组。
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 shortproperty, GetValue()will return a boxed short, which you cannot then typecast as an int; you have to unbox it to a shortfirst. Using Convert.ToInt32()will perform all of the needed steps to get an intvalue out of any property that is convertible toan integer.
要转换您返回的值,您可以使用类型转换,或者如果您想要更灵活一点,请使用 Convert 类的方法。不同之处在于,例如,如果您有一个short属性,GetValue()将返回一个盒装的 short,然后您不能将其类型转换为int; 你必须先把它拆箱short。UsingConvert.ToInt32()将执行所有需要的步骤,以从可转换为整数int的任何属性中获取值。
Converting between reference types is easier since you can just use isand asfor that; those work just like you'd expect with "reflected" property values.
引用类型之间的转换更容易,因为您只需使用isand 即可as;这些工作就像您期望的“反射”属性值一样。
回答by Daniel Hilgarth
GetPropertiesindeed is the correct method.
GetProperties确实是正确的方法。
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 PropertyInfoobject is not bound to any specific class instance.
您需要传递要从中获取值的实例,因为PropertyInfo对象未绑定到任何特定的类实例。
Please consider following the standard .NET naming rules.
请考虑遵循标准的 .NET 命名规则。
This would lead to the following:
这将导致以下情况:
NewSystemAlarminstead of New_systemAlarmnewSystemAlarmor _newSystemAlarminstead of _new_systemAlarmNewTestInspectionExtensionBasesinstead of New_testinspectionExtensionBasesNewTestInspectionIdinstead of New_testinspectionId
NewSystemAlarm代替New_systemAlarmnewSystemAlarm或_newSystemAlarm代替_new_systemAlarmNewTestInspectionExtensionBases代替New_testinspectionExtensionBasesNewTestInspectionId代替代替New_testinspectionId
回答by sovanesyan
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).
如果您使用的是 OpenAccess,您始终可以使用有关模型类的完整信息。那里的信息是从您的映射中检索到的,这意味着您不需要反映您的类(没有开销)。
Just browse trough context.Metadata.PersistentTypes for all of your classes mapping information.
只需通过 context.Metadata.PersistentTypes 浏览所有类映射信息。

