views:

44

answers:

3
public class Address
{
    public string AddressLine1 { get; set; }
    public string AddressLine2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string Zip { get; set; }
}
......
var emp1Address = new Address();
emp1Address.AddressLine1 = "Microsoft Corporation";
emp1Address.AddressLine2 = "One Microsoft Way";
emp1Address.City = "Redmond";
emp1Address.State = "WA";
emp1Address.Zip = "98052-6399";

Consider above class and later its initialization. Now at some point I want to log its state when error occurs. I would like to get the string log somewhat like below.

string toLog = Helper.GetLogFor(emp1Address);

sting toLog should look something like below.

AddressLine1 = "Microsoft Corporation";
AddressLine2 = "One Microsoft Way";
City = "Redmond";
State = "WA";
Zip = "98052-6399";

And then I will log toLog string.

How can I access all the property names and property values of an object within Helper.GetLogFor() method?

Solution that I implemented:-

/// <summary>
/// Creates a string of all property value pair in the provided object instance
/// </summary>
/// <param name="objectToGetStateOf"></param>
/// <exception cref="ArgumentException"></exception>
/// <returns></returns>
public static string GetLogFor(object objectToGetStateOf)
{
  if (objectToGetStateOf == null)
  {
    const string PARAMETER_NAME = "objectToGetStateOf";
    throw new ArgumentException(string.Format("Parameter {0} cannot be null", PARAMETER_NAME), PARAMETER_NAME);
  }
  var builder = new StringBuilder();

  foreach (var property in objectToGetStateOf.GetType().GetProperties())
  {
    object value = property.GetValue(objectToGetStateOf, null);

        builder.Append(property.Name)
        .Append(" = ")
        .Append((value ?? "null"))
        .AppendLine();
  }
  return builder.ToString();
}
+2  A: 
static void Log(object @object)
{
    foreach (var property in @object.GetType().GetProperties())
        Console.WriteLine(property.Name + ": " + property.GetValue(@object, null).ToString());
}
Hasan Khan
The `ToString` call would cause a `NullReferenceException` for a null property value.
Bryan Watts
I had to put a null check before accessing the value of property.
Ismail
+1  A: 

You can access the property name using reflection like following

Type t = emp1Address.GetType();


PropertyInfo [] pi = t.GetProperties();
   foreach (PropertyInfo p in pi)
   {

     //You can get the value (using GetValue() method) and name (p.Name) here.



   }
Prakash Kalakoti
+2  A: 
public static string GetLogFor(object target)
{
    var properties =
        from property in target.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance)
        select new
        {
            Name = property.Name,
            Value = property.GetValue(target, null)
        };

    var builder = new StringBuilder();

    foreach(var property in properties)
    {
        builder
            .Append(property.Name)
            .Append(" = ")
            .Append(property.Value)
            .AppendLine();
    }

    return builder.ToString();
}
Bryan Watts
`Argument typ 'object' is not assignable to parameter type 'string'` compilation error on `builder.Append(property.Name).Append(" = ").AppendLine(property.Value);` statement
Ismail
Can you please help me understand what does `.GetProperties(BindingFlags.Public | BindingFlags.Instance)` mean?
Ismail
@Ismail: I have updated my code to remove that error. I never noticed that `AppendLine` doesn't have the same set of overloads as `Append`.
Bryan Watts
@Ismail: That line of code means "Get all properties which are public and are defined per-instance (as opposed to static)".
Bryan Watts
@Bryan! Thanks a million ton for sharing that bit of information with me.
Ismail
And also thanks for that update
Ismail