Wednesday, November 28, 2007




When the pros of using reflection outweigh the cons, you can take advantage of using it when iterating over properties of classes.  To help with debugging, you can override the ToString() of your classes to return a string that contains the name of any public properties along with their corresponding values:

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            Type t = this.GetType();

            PropertyInfo[] pInfo = t.GetProperties();

            sb.Append(t.ToString() + "\r\n");

            foreach (PropertyInfo p in pInfo)
            {
                string fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, null));

                sb.Append(fmt + "\r\n");
            }

            return sb.ToString();
        }

The function uses reflection to get the public properties of the class and it iterates over the collection of properties and builds a string that represents the state of the class.  The string returned from ToString() would look like this:

Property1 = Value1
Property2 = Value2
.
.
.

The PropertyInfo.GetValue() function takes two parameters; the first parameter is the reference to this, while the second parameter is an object array that is used when the PropertyInfo references an indexed property.  When using reflection to enumerate properties on a class that contains other classes, you must accomodate the case where a class might contain an indexed property:

public class Details
{
        public EDIProcess.Model.EstimateDetailType this[int index]
        {
            get { return (EDIProcess.Model.EstimateDetailType) DetailCollection[index]; }
        }
}

In this case, the Details class contains an indexer that is used to retrieve EstimateDetailType objects by index from the DetailCollection property.  You can use the GetValue() function and pass in an object array that contains a single entry that is the value of the offset into the collection, which will reference the indexed item at that position within the collection.

public class Details
{
        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();

            try
            {
                Type t = this.GetType();
                string fmt;

                PropertyInfo[] pInfo = t.GetProperties();


                sb.Append(t.ToString() + "\r\n");

                foreach (PropertyInfo p in pInfo)
                {
                    if (p.Name == "Item")
                    {
                        for (int i = 0; i < Count; i++)
                        {
                            fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, new object[] { i }));
                            sb.Append(fmt + "\r\n");
                        }
                    }
                    else
                    {
                        fmt = string.Format("{0} = {1}", p.Name, p.GetValue(this, null));
                        sb.Append(fmt + "\r\n");
                    }
                }
            }
            catch (Exception ex)
            {
                log.Error(ex.Message);
            }

            return sb.ToString();
    }
}

The items in bold represent the changes to support the indexed properties.  The Details class contains a DetailCollection class (which derives from ArrayList), and the Details class contains an indexer to retrieve an item from the collection as well as a property that returns the number of items stored in the collection.  The modification looks for a property named Item in the Details class, and it then retrieves the count of objects in the collection and for each object in the collection it calls the GetValue(), passing in a reference to the Details class (this) and a new object[] array that contains a single member that stores the integer value of the item within the collection.




This page is powered by Blogger. Isn't yours?