I've recently answered a question here, where the goal is to mimic some functions from System.Reflection in order to avoid it's direct usage as much as possible, because it works slow.Currently available features are :Cloning properties from one instance to another.Setting properties of instances.Getting property values from instances.Set instance properties to default values, where the values are determined at the creation of the TypeAccessor<T> class.Creating new instances of the type argument T, using default constructor, again this is specified at the instantiation of the TypeAccessor<T> classThe OP's code is really good but I've decided to add a compile time type-safety  to avoid misspelling a variable names.It works with a GetterCache and a SetterCache which are separated for faster lookup.It uses both a private method which is not compile-time typesafe and is used only internally and a public one which is compile-time typesafe and this is the method that you can call outside of the class, so the user won't be able to mess up his naming. But inside the class, we can't know what the type argument T is, so we still need to use some methods which work with string as parameters instead of Expression.public class TypeAccessor<T>{    private readonly Func<T, T> m_applyDefaultValues;    private readonly Func<T> m_constructType;    public ReadOnlyCollection<string> CloneableProperties { get; }    public ReadOnlyDictionary<string, Func<T, object>> GetterCache { get; }    public ReadOnlyDictionary<string, Action<T, object>> SetterCache { get; }    public TypeAccessor(T defaultValue, bool includeNonPublic = false)    {        PropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Instance |                                                            (includeNonPublic                                                                ? BindingFlags.NonPublic                                                                : BindingFlags.Default) |                                                            BindingFlags.Public);        GetterCache = new ReadOnlyDictionary<string, Func<T, object>>(properties.Select(propertyInfo => new            {                PropertyName = propertyInfo.Name,                PropertyGetAccessor = propertyInfo.GetGetAccessor<T>(includeNonPublic)            }).Where(a => a.PropertyGetAccessor != null)            .ToDictionary(a => a.PropertyName, a => a.PropertyGetAccessor));        SetterCache = new ReadOnlyDictionary<string, Action<T, object>>(properties.Select(propertyInfo => new            {                PropertyName = propertyInfo.Name,                PropertySetAccessor = propertyInfo.GetSetAccessor<T>(includeNonPublic)            }).Where(a => a.PropertySetAccessor != null)            .ToDictionary(a => a.PropertyName, a => a.PropertySetAccessor));        CloneableProperties = Array.AsReadOnly(GetterCache.Keys.Intersect(SetterCache.Keys).ToArray());        if (typeof(T).IsValueType)        {            m_applyDefaultValues = instance => defaultValue;            m_constructType = () => defaultValue;        }        else if (defaultValue != null)        {            var defaultConstructor = GetDefaultConstructor();            var propertyValues = GetProperties(defaultValue, CloneableProperties).ToArray();            m_applyDefaultValues = instance =>            {                SetProperties(instance, propertyValues);                return instance;            };            m_constructType = () => m_applyDefaultValues(defaultConstructor());        }        else        {            m_applyDefaultValues = instance => default(T);            m_constructType = () => default(T);        }    }    public void CloneProperties(T source, T target)    {        SetProperties(target, GetProperties(source, CloneableProperties));    }    public void SetToDefault(ref T instance)    {        instance = m_applyDefaultValues(instance);    }    public T New()    {        return m_constructType();    }    private Dictionary<string, object> GetProperties(T instance, IEnumerable<string> properties)        => properties?.ToDictionary(propertyName => propertyName,               propertyName => GetProperty(instance, propertyName)) ?? new Dictionary<string, object>();    public Dictionary<string, object> GetProperties(T instance,        IEnumerable<Expression<Func<T, object>>> properties)        => properties?.ToDictionary(property => GetMemberInfo(property).Name,               property => GetProperty(instance, property)) ?? new Dictionary<string, object>();    public Dictionary<string, object> GetProperties(T instance)        => GetterCache.Keys.ToDictionary(key => key, key => GetProperty(instance, key));    private object GetProperty(T instance, string propertyName)        => GetterCache[propertyName].Invoke(instance);    public TValue GetProperty<TValue>(T instance, Expression<Func<T, TValue>> property)        => (TValue) GetterCache[GetMemberInfo(property).Name](instance);    private void SetProperty(T instance, string propertyName, object value)    {        Action<T, object> setter;        if (SetterCache.TryGetValue(propertyName, out setter))        {            setter(instance, value);        }        else        {            throw new KeyNotFoundException(                $a property setter with the name does not {propertyName} exist on {typeof(T).FullName});        }    }    public void SetProperty<TValue>(T instance, Expression<Func<T, TValue>> property, TValue value)        => SetterCache[GetMemberInfo(property).Name](instance, value);    private void SetProperties<TValue>(T instance, IEnumerable<KeyValuePair<string, TValue>> properties)    {        if (properties != null)        {            foreach (var property in properties)            {                SetProperty(instance, property.Key, property.Value);            }        }    }    public void SetProperties<TValue>(T instance,        IEnumerable<KeyValuePair<Expression<Func<T, TValue>>, TValue>> propertiesInfo)    {        foreach (var propertyInfo in propertiesInfo)        {            SetterCache[GetMemberInfo(propertyInfo.Key).Name](instance, propertyInfo.Value);        }    }    private MemberInfo GetMemberInfo(Expression expression)    {        LambdaExpression lambda = (LambdaExpression) expression;        MemberExpression memberExpr = null;        switch (lambda.Body.NodeType)        {            case ExpressionType.Convert:                memberExpr =                    ((UnaryExpression) lambda.Body).Operand as MemberExpression;                break;            case ExpressionType.MemberAccess:                memberExpr = lambda.Body as MemberExpression;                break;        }        return memberExpr.Member;    }    private static Func<T> GetDefaultConstructor()    {        var type = typeof(T);        if (type == typeof(string))        {            return                Expression.Lambda<Func<T>>(Expression.TypeAs(Expression.Constant(null), typeof(string))).Compile();        }        if (type.HasDefaultConstructor())        {            return Expression.Lambda<Func<T>>(Expression.New(type)).Compile();        }        return () => (T) FormatterServices.GetUninitializedObject(type);    }}These are the extension classes:public static class TypeAccessor{    /// <summary>    /// Creates a new instance of the <see cref=TypeAccessor{_}/> class using the specified <see cref=T/>.    /// </summary>    public static TypeAccessor<T> Create<T>(T instance, bool includeNonPublic = false)    {        return new TypeAccessor<T>(instance, includeNonPublic);    }}public static class TypeExtensions{    public static bool HasDefaultConstructor(this Type type)    {        return (type.IsValueType || (type.GetConstructor(Type.EmptyTypes) != null));    }}public static class PropertyInfoExtensions{    /// <summary>    /// Generates an <see cref=Expression{Func{_,_}}/> that represents the current <see cref=PropertyInfo/>'s getter.    /// </summary>    public static Expression<Func<TSource, TProperty>> GetGetAccessor<TSource, TProperty>(        this PropertyInfo propertyInfo, bool includeNonPublic = false)    {        var getMethod = propertyInfo.GetGetMethod(includeNonPublic);        if (getMethod != null && propertyInfo.GetIndexParameters().Length == 0)        {            var instance = Expression.Parameter(typeof(TSource), instance);            var value = Expression.Call(instance, getMethod);            return Expression.Lambda<Func<TSource, TProperty>>(                propertyInfo.PropertyType.IsValueType                    ? Expression.Convert(value, typeof(TProperty))                    : Expression.TypeAs(value, typeof(TProperty)),                instance            );        }        else        {            return null;        }    }    /// <summary>    /// Generates a <see cref=Func{_,_}/> delegate to the current <see cref=PropertyInfo/>'s getter.    /// </summary>    /// <param name=includeNonPublic>Indicates whether a non-public get accessor should be returned.</param>    public static Func<TSource, object> GetGetAccessor<TSource>(this PropertyInfo propertyInfo,        bool includeNonPublic = false)    {        return propertyInfo.GetGetAccessor<TSource, object>(includeNonPublic)?.Compile();    }    /// <summary>    /// Generates an <see cref=Expression{Action{_,_}};/> that represents the current <see cref=PropertyInfo/>'s setter.    /// </summary>    /// <param name=includeNonPublic>Indicates whether a non-public set accessor should be returned.</param>    public static Expression<Action<TSource, TProperty>> GetSetAccessor<TSource, TProperty>(        this PropertyInfo propertyInfo, bool includeNonPublic = false)    {        var setMethod = propertyInfo.GetSetMethod(includeNonPublic);        if (setMethod != null && propertyInfo.GetIndexParameters().Length == 0)        {            var instance = Expression.Parameter(typeof(TSource), instance);            var value = Expression.Parameter(typeof(TProperty), value);            return Expression.Lambda<Action<TSource, TProperty>>(                Expression.Call(                    instance,                    setMethod,                    propertyInfo.PropertyType.IsValueType                        ? Expression.Convert(value, propertyInfo.PropertyType)                        : Expression.TypeAs(value, propertyInfo.PropertyType)                ),                instance,                value            );        }        else        {            return null;        }    }    /// <summary>    /// Generates an <see cref=Action{_,_}/> delegate to the current <see cref=PropertyInfo/>'s setter.    /// </summary>    /// <param name=includeNonPublic>Indicates whether a non-public set accessor should be returned.</param>    public static Action<TSource, object> GetSetAccessor<TSource>(this PropertyInfo propertyInfo,        bool includeNonPublic = false)    {        return propertyInfo.GetSetAccessor<TSource, object>(includeNonPublic)?.Compile();    }}Here's a usage example:public class Point2D{    public double X { get; set; }    public double Y { get; set; }}var pointA = new Point2D {X = 9000.01, Y = 0.0};var accessor = TypeAccessor.Create(pointA);var pointB = new Point2D();//obtains properties by name with compile time safetyDictionary<string, object> a = accessor.GetProperties(pointA, new List<Expression<Func<Point2D, object>>>{    d => d.X,    d => d.Y});accessor.CloneProperties(pointA, pointB); // pointB.X should now be 9000.01accessor.SetProperty(pointA, p => p.X, 0.0); // sets pointA.X to 0.0Console.WriteLine(accessor.GetProperty(pointA, p => p.X)); // prints pointA.X, should be 0.0accessor.SetToDefault(ref pointA); // sets pointA's properties to default the accessor's default valuesConsole.WriteLine(accessor.GetProperty(pointA, p => p.X)); // prints pointA.X, should be 9000.01
Accessing properties by name with compile-time typesafety
c#;performance;generics;lambda;rags to riches
Expressions & Factoriesvar getMethod = propertyInfo.GetGetMethod(includeNonPublic);if (getMethod != null && propertyInfo.GetIndexParameters().Length == 0){    var instance = Expression.Parameter(typeof(TSource), instance);    var value = Expression.Call(instance, getMethod);    return Expression.Lambda<Func<TSource, TProperty>>(        propertyInfo.PropertyType.IsValueType            ? Expression.Convert(value, typeof(TProperty))            : Expression.TypeAs(value, typeof(TProperty)),        instance    );}You call here the delegate via an expression (the setter does the same). This is like you've just called the delegate.Use can use the Property expression to call the property directly:public static Expression<Func<T, TProperty>> CreateGetterExpression<T, TProperty>(            this PropertyInfo propertyInfo,            bool nonPublic = false){    var hasGetter = propertyInfo.GetGetMethod(nonPublic) != null;    if (!hasGetter || propertyInfo.GetIndexParameters().Any())    {        return null;    }    var obj = Expression.Parameter(typeof(T), obj);    var property = Expression.Property(obj, propertyInfo);    return Expression.Lambda<Func<T, TProperty>>(property, obj);}Less nesting is usually better so if there is no getter or it's an indexer you can return right away.The other method for creating setteers can be made pretty in a similar manner:public static Expression<Action<T, TProperty>> CreateSetterExpression<T, TProperty>(        this PropertyInfo propertyInfo,        bool nonPublic = false){    var hasSetter = propertyInfo.GetSetMethod() != null;    if (!hasSetter || propertyInfo.GetIndexParameters().Any())    {        return null;    }    var obj = Expression.Parameter(typeof(T), obj);    var value = Expression.Parameter(typeof(TProperty), value);    var property = Expression.Property(obj, propertyInfo);    return Expression.Lambda<Action<T, TProperty>>(        Expression.Assign(property, value), obj, value    );}We still need expressions for indexed properties. Here's an example for a property with a single index. I think more then two are not necessary.public static Expression<Func<T, TIndex1, TProperty>> CreateGetterExpression<T, TIndex1, TProperty>(        this PropertyInfo propertyInfo,        bool nonPublic = false){    var hasGetter = propertyInfo.GetGetMethod(nonPublic) != null;    if (!hasGetter || propertyInfo.GetIndexParameters().Length != 1)    {        return null;    }    var obj = Expression.Parameter(typeof(T), obj);    var index1 = Expression.Parameter(typeof(TIndex1), i);    var property = Expression.Property(obj, propertyInfo, index1);    return Expression.Lambda<Func<T, TIndex1, TProperty>>(property, obj, index1);}The class that contains the above methods is PropertyInfoExtensions. I think it's not a good name. Even though they are extensions you should try to find a name that better describes the functionality the class contains. Here I find the name ExpressionFactory good because this class is a factory. It creates expressions. Consequently need its methods also new names like CreateSomething. GetSomething implies you already have it somewhere and just retrieve it which is not the case here.Constructorsprivate static Func<T> GetDefaultConstructor(){    var type = typeof(T);    if (type == typeof(string))    {        return Expression.Lambda<Func<T>>(            Expression.TypeAs(Expression.Constant(null),             typeof(string))        ).Compile();    }    if (type.HasDefaultConstructor())    {        return Expression.Lambda<Func<T>>(Expression.New(type)).Compile();    }    return () => (T)FormatterServices.GetUninitializedObject(type);}This is tricky. The string does not have a default constructor. This means that the New() method should throw an InvalidOperationException for types without a default constructor. An empty instance of a string is of no use. Strings are immutable so you cannot set anything useful and therefore it should be forbidden to create one.In such cases the tester-doer pattern is recommendable. To implement it you'd need to add a property like HasDefaultConstructor or CanCreateNew. This would be the tester. New() is the doer.There is one more issue in this method. The usage of this is invalid:FormatterServices.GetUninitializedObject(..)FormatterServices.GetUninitializedObject MethodBecause the new instance of the object is initialized to zero and no constructors are run, the object might not represent a state that is regarded as valid by that object. The current method should only be used for deserialization when the user intends to immediately populate all fields. It does not create an uninitialized string, since creating an empty instance of an immutable type serves no purpose.Returning this from the New() is of no use. No default constructor -> exception. All other workarounds do only harm.Creating TypeAccessorPropertyInfo[] properties = typeof(T).GetProperties(BindingFlags.Instance |                                                    (includeNonPublic                                                        ? BindingFlags.NonPublic                                                        : BindingFlags.Default) |                                                    BindingFlags.Public);You need to admit that this is quite ugly. But what do we have helper variables for?var nonPublicFlag = includeNonPublic ? BindingFlags.NonPublic : BindingFlags.Default;var properties = typeof(T).GetProperties(BindingFlags.Instance| BindingFlags.Public | nonPublicFlag);Looks better, doesn't it? ;-)GetterCache = new ReadOnlyDictionary<string, Func<T, object>>(properties.Select(propertyInfo => new{    ...})Another unecessarily long line. A dictionary implements the IReadOnlyDictionary interface. If we change the type of the GetterCache property topublic IReadOnlyDictionary<string, Func<T, object>> GetterCache { get; }we no longer need the new ReadOnlyDictionary because an implicit cast will work:GetterCache = properties.Select(propertyInfo => new{    ..}).Where(a => a.GetterDelegate != null).ToDictionary(a => a.PropertyName, a => a.GetterDelegate);Getting and setting propertiesprivate object GetProperty(T instance, string propertyName)    => GetterCache[propertyName].Invoke(instance);public TValue GetProperty<TValue>(T instance, Expression<Func<T, TValue>> property)    => (TValue) GetterCache[GetMemberInfo(property).Name](instance);private void SetProperty(T instance, string propertyName, object value){    Action<T, object> setter;    if (SetterCache.TryGetValue(propertyName, out setter))    {        setter(instance, value);    }    else    {        throw new KeyNotFoundException(            $a property setter with the name does not {propertyName} exist on {typeof(T).FullName});    }}public void SetProperty<TValue>(T instance, Expression<Func<T, TValue>> property, TValue value)    => SetterCache[GetMemberInfo(property).Name](instance, value);These methods are implemented in a very inconsitant way. Only one checks if the property exists in the dictionary, the other ones will crash. There's also a lot of repetition. The entire logic should be in only one getter/setter and the other overloads should call the main method. Lastly I think their names should be changed to GetValue/SetValue because this is what they do.   public void CloneProperties(T source, T target)   {        SetProperties(target, GetProperties(source, CloneableProperties));   }    public void SetToDefault(ref T instance)    {        instance = _applyDefaultValues(instance);    }There's no need for these methods. You can always call accessor.SetValue(prop, default(int));or write an extension for either one.