0

So I have thousands of objects, of generic type T, and I want to cast them to an array of objects I got. So I have to get the properties list T, and for each property set the value to the corresponding object on the array

for (int i = 0; reader.Read(); i++)
{
    T tmp = (T)Activator.CreateInstance(typeof(T));
    foreach (var prop in properties)
    {         
        prop.SetValue(tmp, reader.GetValue(reader.GetOrdinal(prop.Name)), null);
    }
}

reader is a DataReader. The problem I have is that prop.SetValue is sadly slow (consumes like 50% of the total excecution time), I've been told to use Dynamic Methods or Expression Trees, I tried using expression trees but from what I understood I have to generate one tree for each value I want to set, which wouldn't be so good. So Dynamic Methods is the other option. Ideally I'd need to create a method SetProp(object, propertyName, value) which I can reuse over and over again.

Community
  • 1
  • 1
gosukiwi
  • 1,569
  • 1
  • 27
  • 44
  • *personally*, I would say "don't use GetOrdinal per cell", although it isn't going to matter much - however, since this is clearly "data-reader" code that has a 1:1 match between property name and column name, I really suggest you look at dapper-dot-net; it is designed for **exactly** this scenario, and makes data access just painless. It is the tool we wrote and use extensively for the majority of our data-access here at Stack Overflow. – Marc Gravell May 16 '12 at 14:46

3 Answers3

4

Look at FastMember; either use it "as is", or steal all the code (DynamicMethod, etc). It does all this, with reflection-cache etc built in. Example usage:

var accessor = TypeAccessor.Create(typeof(T)); 
for (int i = 0; reader.Read(); i++)
{
    T tmp = (T)Activator.CreateInstance(typeof(T));
    foreach (var prop in properties)
    {         
        accessor[tmp, propName] = newValue; // fill in name/value here
    }
}

alternatively - use something like dapper-dot-net, that does that and handles all the materialization (since this is obviously data-access code).

Marc Gravell
  • 1,026,079
  • 266
  • 2,566
  • 2,900
  • Only +1 cause I can't vote 10 times, from a quick look it works great...I **must** update my code! – Adriano Repetti May 16 '12 at 14:42
  • 1
    There's also `ObjectAccessor` for that object-by-object code; I should also note that it supports the `dynamic` API too (so you can use it to talk to a runtime-property-bound object) – Marc Gravell May 16 '12 at 14:43
3

I tried using expression trees but from what I understood I have to generate one tree for each value I want to set, which wouldn't be so good.

Why not? You'd basically build a List<Tuple<string, Action<object>>> by creating (and then compiling) an expression tree for each property in T. Then you iterate over the list and fetch the item for each property, then call the corresponding action.

I have a PropertyCopy class in MiscUtil which does something very similar - you may want to look at that for inspiration.

Alternatively, as of .NET 4 you could build a single Block expression tree which does all the property setting.

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0

You can create a single expression tree for each property.
Just take the value as a parameter:

var instance = Expression.Parameter(typeof(T));
var value = Expression.Parameter(typeof(object));
var setter = Expression.Lambda(
    Expression.SetProperty(instance, Expression.Cast(value, prop.PropertyType)),
    instance, value
);

You would create and compile these expression trees once per instance type (typically in a static generic class).

While you're at it, you can probably make it even faster by compiling another expression tree instead of Activator.CreateInstance().

Community
  • 1
  • 1
SLaks
  • 868,454
  • 176
  • 1,908
  • 1,964