Skip to content

Instantly share code, notes, and snippets.

@jasondentler
Created April 23, 2014 16:28
Show Gist options
  • Select an option

  • Save jasondentler/11222385 to your computer and use it in GitHub Desktop.

Select an option

Save jasondentler/11222385 to your computer and use it in GitHub Desktop.

Revisions

  1. jasondentler created this gist Apr 23, 2014.
    65 changes: 65 additions & 0 deletions ReflectionExtensions.cs
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,65 @@
    using System;
    using System.Collections.Generic;
    using System.Data;
    using System.Linq;
    using System.Linq.Expressions;
    using System.Reflection;

    namespace Reporting
    {
    public static class ReflectionExtensions
    {

    public static TInstanceType Convert<TInstanceType>(this DataRow row) where TInstanceType : new()
    {
    var retval = new TInstanceType();

    foreach (var propName in SetterDelegateCache<TInstanceType>.WritablePropertyNames)
    {
    var value = row.IsNull(propName) ? null : row[propName];
    SetterDelegateCache<TInstanceType>.Write(propName, retval, value);
    }

    return retval;
    }

    private static class SetterDelegateCache<TInstanceType>
    {
    private static readonly Dictionary<string, Action<TInstanceType, object>> Setters;

    static SetterDelegateCache()
    {
    Setters = typeof (TInstanceType)
    .GetProperties()
    .Where(p => p.CanWrite)
    .ToDictionary(pi => pi.Name, BuildSetDelegate<TInstanceType>);
    }

    public static IEnumerable<string> WritablePropertyNames
    {
    get { return Setters.Keys; }
    }

    public static void Write(string propertyName, TInstanceType instance, object value)
    {
    Setters[propertyName](instance, value);
    }

    }

    private static Action<TInstanceType, object> BuildSetDelegate<TInstanceType>(PropertyInfo pi)
    {
    var instanceParam = Expression.Parameter(typeof(TInstanceType), "row");
    var valueParam = Expression.Parameter(typeof(object), "value");

    var convert = Expression.Convert(valueParam, pi.PropertyType);
    var property = Expression.Property(instanceParam, pi);
    var assign = Expression.Assign(property, convert);

    var lambda = Expression.Lambda<Action<TInstanceType, object>>(assign, instanceParam, valueParam);

    return lambda.Compile();
    }

    }
    }