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 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.
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?
EDIT after 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.
You have to access the ACTUAL object that you need to use reflection on. Here is what I mean:
Instead of this:
Do this (edited based on comment):
Look at this post for more information: Using reflection to set a property of a property of an object
I use following method to get the values from (nested classes) properties like
"Property"
"Address.Street"
"Address.Country.Name"
Here is the Fiddle: https://dotnetfiddle.net/PvKRH0
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).
My internet connection was down when I need to solve the same problem, so I had to 're-invent the wheel':
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.
I know I'm a bit late to the party, and as others said, your implementation is fine
...for simple use cases.
However, I've developed a library that solves exactly that use case, Pather.CSharp.
It is also available as Nuget Package.
Its main class is
Resolver
with itsResolve
method.You pass it an object and the property path, and it will return the desired value.
But it can also resolve more complex property paths, including array and dictionary access.
So, for example, if your
Customer
had multiple addressesyou could access the second one using
Addresses[1]
.