Click here to Skip to main content
15,891,607 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
I have a data set that is in a peculiar setup - an array of "column" classes with properties "Name", "DataType" and "Values"

The latter property is an array of values e.g.

C#
public partial class UsageColumn  {

    private string nameField;

    private string dataTypeField;

    private object[] valuesField;


    public string Name {
        get {
            return this.nameField;
        }
        set {
            this.nameField = value;
        }
    }

    public string DataType {
        get {
            return this.dataTypeField;
        }
        set {
            this.dataTypeField = value;
        }
    }

    public object[] Values {
        get {
            return this.valuesField;
        }
        set {
            this.valuesField = value;
        }
    }

    }
}


I am currently turning this into a .NET collection thus:-
public static List<TRecord> ConvertResultToList<TRecord>(object[] columns, int rowCount) where TRecord : DTO.IDataScopeDTOClass
{
    List<TRecord> ret = new List<TRecord>();

    // The object that we got in columns should have a property called Name and a property called DataType and Values[]
    if (rowCount > 0)
    {
        if (columns.Count() > 0)
        {
            System.Reflection.PropertyInfo piName = columns[0].GetType().GetProperty(@"Name" );
            System.Reflection.PropertyInfo piDataType = columns[0].GetType().GetProperty(@"DataType");
            System.Reflection.PropertyInfo piValues = columns[0].GetType().GetProperty(@"Values");

            System.Reflection.ConstructorInfo ciTarget = typeof(TRecord).GetConstructor(Type.EmptyTypes );


            for (int i = 0; i < rowCount ; i++)
            {
                TRecord newValue = (TRecord)ciTarget.Invoke(null);
                foreach (var thisColumn in columns)
                {
                    string name = piName.GetValue(thisColumn).ToString();
                    string dataType = piDataType.GetValue(thisColumn).ToString();
                    object[] value = (object[])piValues.GetValue(thisColumn);
                    newValue.SetProperty(name, dataType, value[i]);
                }
                ret.Add(newValue);
            }

        }


    }

    return ret;
}


However the line object[] value = (object[])piValues.GetValue(thisColumn); is copying the whole array every time. How do I just get the value at index [i] ?
Posted
Updated 4-Jul-14 0:28am
v2

1 solution

It's not copying the array; it's just getting a reference to the existing array.

You could retrieve a single value using reflection, but that would almost certainly be slower than casting the value to an array and accessing it directly:
C#
System.Reflection.MethodInfo miGet = piValues.PropertyType.GetMethod("Get");
...
object values = piValues.GetValue(thisColumn);
object value = miGet.Invoke(values, new object[] { i });
newValue.SetProperty(name, dataType, value);



Other comments:

A call to GetType() is slow; you should cache and re-use the result of columns[0].GetType():
C#
Type columnType = columns[0].GetType();
System.Reflection.PropertyInfo piName = columnType.GetProperty(@"Name" );
System.Reflection.PropertyInfo piDataType = columnType.GetProperty(@"DataType");
System.Reflection.PropertyInfo piValues = columnType.GetProperty(@"Values");


You can avoid calling the TRecord's constructor via reflection by adding a new() constraint to the type parameter:
C#
where TRecord : DTO.IDataScopeDTOClass, new()
...
TRecord newValue = new TRecord();
 
Share this answer
 
Comments
Duncan Edwards Jones 4-Jul-14 8:46am    
Excellent thanks - I had completely forgotten the new() constraint.. many minds make code work :-)

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