views:

810

answers:

2

I'm trying to create an export Excel/CSV function that will iterate through a custom object and first output the property names and then output the values. I want to use reflection only where necessary so I'm attempting to save the property names when I output the headers and then reuse them to print the values.

Is this possible? I'm a little weary of using reflection in a loop but is there a better way?

Psuedo Code:

Dim Cust1 = New Customer("Tom", "123 Main Street")
Dim Cust2 = New Customer("Mike", "456 Main Street")
Dim Cust3 = New Customer("Joe", "789 Main Street")
Dim CustList As New Arraylist()
CustList.Add(Cust1)
CustList.Add(Cust2)
CustList.Add(Cust3)

CSVExport(CustList, New Customer())


Function CSVExport(List As ArrayList, CustomObject as Object) As StringWriter
Dim sw as Stringwriter
dim proplist as arraylist

'output header

Foreach CustProperty as System.Reflection.PropertyInfo CustomObject.GetType().GetProperties()
    proplist.add(CustProperty.Name)
    sw.write(CustProperty + ",")
EndFor

'output body
'??
'??  Here I'd like to loop through PropList and List instead of using reflection
'??

Return Sw

End Function
A: 

In your Pseudo Code you're already populating an arraylist using reflection. If all you want to do is loop through the ArrayList, you can have a look at the ArrayList Class MSDN entry. It shows how to implement IEnumerable to iterate your array list, e.g:

Dim obj As [Object]

For Each obj In CType(myList, IENumberable)
    Console.Write(" : {0}", obj)
Next obj

That's untested as is, I'm not sure if it should be CType(myList, IENumberable) or DirectCast(myList, IENumberable).

There is another option, using Object Serialization in VB.Net, a road far less traveled (at least around our offices).

Mr. Smith
Will this ensure that the values are iterated in the same order as the property names?
mga911
Yes, I think so. I'm doing something similar on a project I'm working on and the properties returned in the same order as I passed them in. As I said though, the code I posted is untested, I work in C#. Let me know if it works out for you!
Mr. Smith
+1  A: 

Its all reflection regardless of whether or not you have the names stored in a list.

Do you have a degree of control over the CustomObject. You could store the info within the CustomObject and query that info instead without using reflection. For instance, this is the code I use for my basic domain objects.

public class DomainObject 
{
    private HashTable _values = new HashTable();

    public HashTable Properties
    {
        get 
        {
             return _values;
        }
    }

    protected void SetValue<T>(string property, T value)
    {
        if (_values.ContainsKey(property))
        {
            _values[property] = value;
        }
        else 
        {
            _values.Add(property, value);
        }
    }

    protected T GetValue<T>(string property)
    {
        if (_values.ContainsKey(property))
        {
            return (T)_values[property];
        }
        else 
        {
            return default(T);
        }
    }
}


public class TootsieRoll : DomainObject 
{
     public string Size
     {
         get { return GetValue<string>("Size"); }
         set { SetValue<string>("Size",value); }
     }

     public string Flavor
     {
        get { return GetValue<string>("Flavor"); }
        set { SetVlaue<string>("Flavor", value); }
     }

    public int Ounces
    {
       get { return GetValue<int>("Ounces"); }
       set { SetValue<int>("Ounces", value); }
    }
}

Now your CSV code would only need to access and loop through the Key=>Value pairs within the "Properties" HashTable it inherited from the DomainObject to get the names and values. But obviously this only works if you have a level of control over your objects necessry to make them inherit from the DomainObject, and it wouldnt involve 30 years of drugery to rewrite all your property accessors. If that is the case, then reflection is your way to go.

Goblyn27