Click here to Skip to main content
15,885,811 members
Please Sign up or sign in to vote.
5.00/5 (1 vote)
See more:
I have a Windows Forms TreeGrid, populated via reflection applied on some bussiness classes I wrote. Each line of the TreeGrid shows my class' properties, along with a column where I can edit the valueof the property.

My problems arise when I have "public xxx[]" on my class. I can populate the tree via code with any number of occurrences of "xxx" object, using buttons "Add" and "Delete". This thing works fine.

But the question is:

How I use reflection to populate my objects from the values of the tree when this objects are arrays, declared but not initialized im my bussiness classes?

When I finish this code, I will post it under an article here in CP.

Any hints or help?

TIA

Nilo
Brazil



UPDATE: The significant portion of my code below:

C#
        /// <summary>
        /// Gets the properties of the current object, creating a tree node for each.
        /// Splits the subtrees recursivelly when a property is found that is told to be arrays type.
        /// </summary>
        /// <param name="obj">object to be inspected</param>
        /// <param name="origin">tree where add the nodes obtained from the object</param>
        private void getProperties(Object obj, ref TreeGridNode origin)
        {
            int qtyItems = 0;
            string value = "";
            PropertyInfo[] propertyInfos;
            TreeGridNode node;
            bool dynamic = false;

            // Gets all the properties of the object
            propertyInfos = obj.GetType().GetProperties();

            // process all the properties from the object, using them to populate the tree 
            foreach (PropertyInfo p in propertyInfos)
            {
                // Properties that originally can't be written are hidden here from the user...
                // It makes no sense alter properties that are read-only... 
                if (!p.CanWrite)
                    continue;

                // The property DeviceID is not used when configuring Lists
                // So, let's hide it from the tree.
                if (p.Name.Equals("DeviceID"))
                    continue;

                // Gets advanced information from the property's dictionary
                //TypeInfo tinfo = dic.getTypeName(p.PropertyType.ToString());

                qtyItems = 1;
                dynamic = false;

                // Add a row for each property, setting your name, type and value
                if (!p.PropertyType.IsArray || p.PropertyType.ToString().Equals("System.Byte[]"))
                {
                    if (p.GetValue(obj, null) != null)
                        value = p.GetValue(obj, null).ToString();
                }
                else
                {
                    if (p.GetValue(obj, null) != null)
                    {
                        Array arr = p.GetValue(obj, null) as Array;
                        qtyItems = arr.Length;
                    }
                    else
                    {
                        qtyItems = 0;
                        dynamic = true;
//-----------------------------------------------------------------------
//  Here I wish to create the dynamic array defined in my original object
//  as 
//
//       "public xxxx[]"
//  
//  Note that I can insert recursively the properties of class "xxxx"
//  when I click on an "Add" button.
//
//  My trouble is set the values I furnish via grid edition on the the
//  object I created.
//
//  When the property is not an "public xxxx[]", my code works like a charm.
//  
//-----------------------------------------------------------------------
                    }
                }

                node = origin.Nodes.Add(p.Name, (dynamic?"":p.PropertyType.ToString()), (qtyItems == 1 ? value : ""), (qtyItems == 1 ? true : false), qtyItems, p, obj, dynamic,false);

                // If the property should have a subtree, recurse starting at it, generating the subtree
                if (qtyItems > 1)
                {
                    for (int i = 1; i <= qtyItems; i++)
                    {
                        // Sets current node color to red
                        node.DefaultCellStyle.ForeColor = Color.Red;

                        // Gets the complete array
                        Array ar = (Array)p.GetValue(obj, null);

                        // Add the node to the newly created subtree
                        TreeGridNode subRoot = node.Nodes.Add(p.Name + " " + i, "", "", false, 1, p.GetValue(obj, null), ar, ar, false,false);

                        // Proceed recursively, startting for the (i)th occurrence of it... 
                        this.getProperties(ar.GetValue(i - 1), ref subRoot);
                    }
                }
            }
        }
Posted
Updated 8-May-12 7:27am
v2
Comments
Ganesan Senthilvel 8-May-12 13:14pm    
Share your code for clarity
Mehdi Gholam 8-May-12 13:14pm    
Are you trying to set values in your entity or get the values?
NiloPaim 8-May-12 14:25pm    
Set values, Mehdi.
wizardzz 8-May-12 13:23pm    
Reason for my vote of 5
5 for offering to post tip or article. Thank you.
NiloPaim 8-May-12 13:25pm    
Question improved with my code.

@wizardzz, thanks for your vote. I'll post the solution when i have it.

1 solution

The most basic steps are:

C#
using System;
using System.Reflection;

//...

class Sample {
    int[] array; // intentionally left private, to demonstrate the effect of Reflection
} //class Sample

//...

Sample sample = new Sample(); // could do it using Reflection, via invocation of a constructor
// but let's focus on the array:
BindingFlags universalBindingFlags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.Static;
Type type = typeof(Sample);
FieldInfo arrayField = type.GetFields(universalBindingFlags)[0]; // just in this case
arrayField.SetValue(sample, new int[] { 1, 2, 3 } /* or something from your tree :-) */ );


This is how to do it with Reflection. Again, it's pretty slow. You can also emit the code in the form of either emitted assembly or in some DynamicMethod. It makes enormous gain in performance (orders of magnitude), if you do reflection part only once and reuse the call to the method(s) many times.

—SA
 
Share this answer
 
v3
Comments
Shahin Khorshidnia 8-May-12 16:24pm    
Good answer.
+5
Sergey Alexandrovich Kryukov 8-May-12 16:46pm    
Thank you, Shahin.
--SA
Wonde Tadesse 8-May-12 17:54pm    
5+
Sergey Alexandrovich Kryukov 8-May-12 18:06pm    
Thank you, Wonde.
--SA
NiloPaim 24-May-12 10:07am    
SAKryukov, I've adapted your code to my real application and it works like a charm. Thank you.

I agree with you about performance, but this is not a problem due the nature of the application.

After finished the work, I'll clean up the code in order to write an independent component. Then I'll post an article and the code.

Thanks to all.
Nilo

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900