Mohit Deshpande
Mohit Deshpande

Reputation: 55217

Recurse through properties of a class

Take this sample class as an example:

    [AttributeUsage(AttributeTargets.All, AllowMultiple=true)]
public class BugFixAttribute : System.Attribute
{
    public int BugId { get; private set; }
    public string Programmer { get; private set; }
    public DateTime Date { get; private set; }
    public string Comments { get; set; }
    public string RefersTo { get; set; }

    public BugFixAttribute(int bugId = 0, string programmer = "")
    {
        this.BugId = bugId;
        this.Programmer = programmer;
        Date = DateTime.Now;
    }
}

And I want to recuse through the properties to use like:

object[] attr = info.GetCustomAttributes(typeof(BugFixAttribute), false);
foreach (object attribute in attr)
{
    BugFixAttribute bfa = (BugFixAttribute) attribute;
    Debug.WriteLine(string.Format("\nBugId: {0}", bfa.BugId));
    Debug.WriteLine(string.Format("Programmer: {0}", bfa.Programmer));
    //...
}

Because what I need to do is to print these to a file. So how can I recurse through the properties instead of doing the Debug.WriteLine() through all of them, is there a way or do I have to write it out.

Upvotes: 3

Views: 490

Answers (5)

pdr
pdr

Reputation: 6440

I love Linq for this kind of thing

var props = from b in info.GetCustomAttributes(typeof(BugFixAttribute), false)
            from p in b.GetType().GetProperties()
            select new { 
                   Name = p.Name,
                   Value = p.GetValue(p.GetValue(b, null))
                   };

foreach(var prop in props)
{
    Debug.WriteLine(string.Format("{0}: {1}", prop.Name, prop.Value));
}

Upvotes: 2

Nick
Nick

Reputation: 5945

I would suggest that this is probably not a great use for Attributes, as it muddies up the meta attached to the code. If you want to standardize a way to get at this sort of information regarding bug fixes, I would suggest coming up with an XML Comment Tag, and then turning on XML Comments for your project, and using that instead.

Example Syntax:

/// <summary>This Method Does Something</summary>
/// <BugFix BugId="1234" Programmer="Bob" Date="2/1/2010">Fix Comments</BugFix>
public void MyMethod()
{
    // Do Something
}

Upvotes: 6

Paul Creasey
Paul Creasey

Reputation: 28824

foreach (var (BugFixAttribute)attribute in attr)
{
    foreach(PropertyInfo prop in attribute.GetType().GetProperties())
    {
        Debug.WriteLine(string.Format("{0}: {1}", prop.name,prop.GetValue(attribute,null));
    }
}

Upvotes: 0

atk
atk

Reputation: 9314

If I read the question correctly, you're looking for a simpler way to write out the class information, right? You've got two options:

  1. reflection, for a highly generic solution that will prolly output way too much information (assuming this is java - or .NET which I've been told is very much the same...)
  2. define the toString() method, and call Debug.WriteLine(bfa)

Solution 1 is probably way overkill. You'll probably get output for stuff you don't want, and you'll not be able to get private values.

Solution 2 is the simple way.

public class BugFixAttribute : System.Attribute
{
 ...

 public String toString(){
   return string.Format("\nBugId: {0}\nProgrammer: {1}", this.BugId, this.Programmer));
 }
}

Upvotes: 0

driis
driis

Reputation: 164281

Yes, if you use reflection:

Type t = bfa.GetType();
PropertyInfo[] properties = t.GetProperties();
foreach(var prop in properties)
{
    Debug.WriteLine(string.Format("{0}: {1}", prop.Name,prop.GetValue(bfa,null)));
}

This will print the name and value of all public properties in bfa. You can check the CanRead property on a PropertyInfo to check if it can be read (ie. if it declares a getter). The example will fail if one of the properties are read-only or is indexed - if this can occur, you need to check for it in the code.

Upvotes: 4

Related Questions