在 C# 中使用反射获取嵌套对象的属性
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1954746/
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
Using reflection in C# to get properties of a nested object
提问by jheddings
Given the following objects:
给定以下对象:
public class Customer {
public String Name { get; set; }
public String Address { get; set; }
}
public class Invoice {
public String ID { get; set; }
public DateTime Date { get; set; }
public Customer BillTo { get; set; }
}
I'd like to use reflection to go through the Invoice
to get the Name
property of a Customer
. Here's what I'm after, assuming this code would work:
我想使用反射Invoice
来获取 a 的Name
属性Customer
。这就是我所追求的,假设这段代码可以工作:
Invoice inv = GetDesiredInvoice(); // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo.Address");
Object val = info.GetValue(inv, null);
Of course, this fails since "BillTo.Address" is not a valid property of the Invoice
class.
当然,这会失败,因为“BillTo.Address”不是Invoice
该类的有效属性。
So, I tried writing a method to split the string into pieces on the period, and walk the objects looking for the final value I was interested in. It works okay, but I'm not entirely comfortable with it:
因此,我尝试编写一种方法,将字符串拆分为句点,然后遍历对象以寻找我感兴趣的最终值。它工作正常,但我对此并不完全满意:
public Object GetPropValue(String name, Object obj) {
foreach (String part in name.Split('.')) {
if (obj == null) { return null; }
Type type = obj.GetType();
PropertyInfo info = type.GetProperty(part);
if (info == null) { return null; }
obj = info.GetValue(obj, null);
}
return obj;
}
Any ideas on how to improve this method, or a better way to solve this problem?
关于如何改进此方法或解决此问题的更好方法的任何想法?
EDITafter posting, I saw a few related posts... There doesn't seem to be an answer that specifically addresses this question, however. Also, I'd still like the feedback on my implementation.
发布后编辑,我看到了一些相关的帖子......但是,似乎没有专门解决这个问题的答案。此外,我仍然希望对我的实施提供反馈。
采纳答案by Reed Copsey
I actually think your logic is fine. Personally, I would probably change it around so you pass the object as the first parameter (which is more inline with PropertyInfo.GetValue, so less surprising).
其实我觉得你的逻辑没问题。就我个人而言,我可能会更改它,以便您将对象作为第一个参数传递(它更符合 PropertyInfo.GetValue,因此不那么令人惊讶)。
I also would probably call it something more like GetNestedPropertyValue, to make it obvious that it searches down the property stack.
我也可能会称它为更像 GetNestedPropertyValue 的东西,以使其明显地向下搜索属性堆栈。
回答by Gabriel McAdams
You have to access the ACTUAL object that you need to use reflection on. Here is what I mean:
您必须访问需要对其使用反射的 ACTUAL 对象。这就是我的意思:
Instead of this:
取而代之的是:
Invoice inv = GetDesiredInvoice(); // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo.Address");
Object val = info.GetValue(inv, null);
Do this (edited based on comment):
这样做(根据评论编辑):
Invoice inv = GetDesiredInvoice(); // magic method to get an invoice
PropertyInfo info = inv.GetType().GetProperty("BillTo");
Customer cust = (Customer)info.GetValue(inv, null);
PropertyInfo info2 = cust.GetType().GetProperty("Address");
Object val = info2.GetValue(cust, null);
Look at this post for more information: Using reflection to set a property of a property of an object
查看此帖子以获取更多信息: 使用反射设置对象的属性的属性
回答by itowlson
You don't explain the source of your "discomfort," but your code basically looks sound to me.
你没有解释你“不舒服”的原因,但你的代码在我看来基本上是合理的。
The only thing I'd question is the error handling. You return null if the code tries to traverse through a null reference or if the property name doesn't exist. This hides errors: it's hard to know whether it returned null because there's no BillTo customer, or because you misspelled it "BilTo.Address"... or because there is a BillTo customer, and its Address is null! I'd let the method crash and burn in these cases -- just let the exception escape (or maybe wrap it in a friendlier one).
我唯一要质疑的是错误处理。如果代码尝试遍历 null 引用或属性名称不存在,则返回 null。这隐藏了错误:很难知道它返回 null 是因为没有 BillTo 客户,还是因为您拼错了“BilTo.Address”……或者因为有 BillTo 客户,而其 Address 为空!在这些情况下,我会让方法崩溃并烧毁 - 只是让异常逃脱(或者可能将其包装在更友好的方法中)。
回答by AaronLS
if (info == null) { /* throw exception instead*/ }
I would actually throw an exception if they request a property that doesn't exist. The way you have it coded, if I call GetPropValue and it returns null, I don't know if that means the property didn't exist, or the property did exist but it's value was null.
如果他们请求不存在的属性,我实际上会抛出异常。你的编码方式,如果我调用 GetPropValue 并且它返回 null,我不知道这是否意味着该属性不存在,或者该属性确实存在但它的值为 null。
回答by ram
Try inv.GetType().GetProperty("BillTo+Address");
尝试 inv.GetType().GetProperty("BillTo+Address");
回答by MalibuCusser
My internet connection was down when I need to solve the same problem, so I had to 're-invent the wheel':
当我需要解决同样的问题时,我的互联网连接中断了,所以我不得不“重新发明轮子”:
static object GetPropertyValue(Object fromObject, string propertyName)
{
Type objectType = fromObject.GetType();
PropertyInfo propInfo = objectType.GetProperty(propertyName);
if (propInfo == null && propertyName.Contains('.'))
{
string firstProp = propertyName.Substring(0, propertyName.IndexOf('.'));
propInfo = objectType.GetProperty(firstProp);
if (propInfo == null)//property name is invalid
{
throw new ArgumentException(String.Format("Property {0} is not a valid property of {1}.", firstProp, fromObject.GetType().ToString()));
}
return GetPropertyValue(propInfo.GetValue(fromObject, null), propertyName.Substring(propertyName.IndexOf('.') + 1));
}
else
{
return propInfo.GetValue(fromObject, null);
}
}
Pretty sure this solves the problem for any string you use for property name, regardless of extent of nesting, as long as everything's a property.
很确定这可以解决您用于属性名称的任何字符串的问题,无论嵌套的程度如何,只要所有内容都是属性即可。
回答by roger l
In hopes of not sounding too late to the party, I would like to add my solution: Definitely use recursion in this situation
为了不让聚会听起来太晚,我想添加我的解决方案:在这种情况下绝对使用递归
public static Object GetPropValue(String name, object obj, Type type)
{
var parts = name.Split('.').ToList();
var currentPart = parts[0];
PropertyInfo info = type.GetProperty(currentPart);
if (info == null) { return null; }
if (name.IndexOf(".") > -1)
{
parts.Remove(currentPart);
return GetPropValue(String.Join(".", parts), info.GetValue(obj, null), info.PropertyType);
} else
{
return info.GetValue(obj, null).ToString();
}
}
回答by BarbaBabak
public static string GetObjectPropertyValue(object obj, string propertyName)
{
bool propertyHasDot = propertyName.IndexOf(".") > -1;
string firstPartBeforeDot;
string nextParts = "";
if (!propertyHasDot)
firstPartBeforeDot = propertyName.ToLower();
else
{
firstPartBeforeDot = propertyName.Substring(0, propertyName.IndexOf(".")).ToLower();
nextParts = propertyName.Substring(propertyName.IndexOf(".") + 1);
}
foreach (var property in obj.GetType().GetProperties())
if (property.Name.ToLower() == firstPartBeforeDot)
if (!propertyHasDot)
if (property.GetValue(obj, null) != null)
return property.GetValue(obj, null).ToString();
else
return DefaultValue(property.GetValue(obj, null), propertyName).ToString();
else
return GetObjectPropertyValue(property.GetValue(obj, null), nextParts);
throw new Exception("Property '" + propertyName.ToString() + "' not found in object '" + obj.ToString() + "'");
}
回答by Mohamed.Abdo
> Get Nest properties e.g., Developer.Project.Name
> Get Nest properties e.g., Developer.Project.Name
private static System.Reflection.PropertyInfo GetProperty(object t, string PropertName)
{
if (t.GetType().GetProperties().Count(p => p.Name == PropertName.Split('.')[0]) == 0)
throw new ArgumentNullException(string.Format("Property {0}, is not exists in object {1}", PropertName, t.ToString()));
if (PropertName.Split('.').Length == 1)
return t.GetType().GetProperty(PropertName);
else
return GetProperty(t.GetType().GetProperty(PropertName.Split('.')[0]).GetValue(t, null), PropertName.Split('.')[1]);
}
回答by DevT
I use following method to get the values from (nested classes) properties like
我使用以下方法从(嵌套类)属性中获取值,例如
"Property"
“财产”
"Address.Street"
“街道地址”
"Address.Country.Name"
“地址.国家.名称”
public static object GetPropertyValue(object src, string propName)
{
if (src == null) throw new ArgumentException("Value cannot be null.", "src");
if (propName == null) throw new ArgumentException("Value cannot be null.", "propName");
if(propName.Contains("."))//complex type nested
{
var temp = propName.Split(new char[] { '.' }, 2);
return GetPropertyValue(GetPropertyValue(src, temp[0]), temp[1]);
}
else
{
var prop = src.GetType().GetProperty(propName);
return prop != null ? prop.GetValue(src, null) : null;
}
}
Here is the Fiddle: https://dotnetfiddle.net/PvKRH0
这是小提琴:https: //dotnetfiddle.net/PvKRH0