Skip to content

Instantly share code, notes, and snippets.

@brandonmartinez
Created October 5, 2018 20:50
Show Gist options
  • Save brandonmartinez/da5c7493167b1dcb5f7574b406111dc5 to your computer and use it in GitHub Desktop.
Save brandonmartinez/da5c7493167b1dcb5f7574b406111dc5 to your computer and use it in GitHub Desktop.
Wrote some code for a project, but ended up scrapping it since we refactored and simplified the calling code. Just wanted to keep the code in case I need to mess with expressions for property getters and setters again.
using System;
using System.Linq.Expressions;
using System.Reflection;
namespace MyProject.Services.SystemExtensions
{
public static class ExpressionExtensions
{
/// <summary>
/// Compiles a getter Func from an expression to access a property
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="propertyExpression"></param>
/// <returns></returns>
public static Func<TModel, TProperty> CompilePropertyExpressionsGetter<TModel, TProperty>(this Expression<Func<TModel, TProperty>> propertyExpression)
{
var compiledGetter = propertyExpression.Compile();
return compiledGetter;
}
/// <summary>
/// Generates a setter action that can be used with a property expression
/// </summary>
/// <typeparam name="TModel"></typeparam>
/// <typeparam name="TProperty"></typeparam>
/// <param name="propertyExpression"></param>
/// <returns></returns>
public static Action<TModel, TProperty> CompilePropertyExpressionsSetter<TModel, TProperty>(this Expression<Func<TModel, TProperty>> propertyExpression)
{
if(!(propertyExpression.Body is MemberExpression member))
{
throw new ArgumentException($"Expression '{propertyExpression}' refers to a method, not a property.");
}
var propertyInfo = member.Member as PropertyInfo;
if(propertyInfo == null)
{
throw new ArgumentException($"Expression '{propertyExpression}' refers to a field, not a property.");
}
var propertyName = propertyInfo.Name;
var targetExpression = Expression.Parameter(typeof(TModel), "Target");
var fieldExpression = Expression.Property(targetExpression, propertyName);
var valueExpression = Expression.Parameter(typeof(TProperty), "value");
var convertExpression = Expression.Call(typeof(Convert), "ChangeType", null, valueExpression, Expression.Constant(fieldExpression.Type));
var valueCast = Expression.Convert(convertExpression, fieldExpression.Type);
var assignmentExpression = Expression.Assign(fieldExpression, valueCast);
var assignmentLambdaExpression = Expression.Lambda<Action<TModel, TProperty>>(assignmentExpression, targetExpression, valueExpression);
var compiledAssignment = assignmentLambdaExpression.Compile();
return compiledAssignment;
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment