Skip to content

Instantly share code, notes, and snippets.

@AptiviCEO
Last active December 25, 2022 14:55
Show Gist options
  • Save AptiviCEO/23ce0a19ffe5cd7e290e083b89808eff to your computer and use it in GitHub Desktop.
Save AptiviCEO/23ce0a19ffe5cd7e290e083b89808eff to your computer and use it in GitHub Desktop.
Fields and properties get and set functions using expression
using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using System.Reflection;
using System.Linq.Expressions;
namespace Aptivi;
class ExpressionGetSet
{
// --------------------------- Test classes ---------------------------
public static class Person
{
public static String Title = "Product Manager";
public static String Name { get; set; } = "John";
}
public class App
{
public String Desc = "Chat on IRC from anywhere, and never miss a message";
public String Name { get; set; } = "IRCCloud";
}
// --------------------------- Get and set property using expression in static mode ---------------------------
private static object ExpressionGetPropertyStatic(Type type, string property)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (property is null)
throw new ArgumentNullException(nameof(property));
var propertyInfo = type.GetProperty(property);
var instanceParam = Expression.Parameter(type);
var callExpr = Expression.Call(propertyInfo.GetGetMethod());
var convExpr = Expression.Convert(callExpr, typeof(Object));
var expression = Expression.Lambda<Func<Object>>(convExpr).Compile();
return expression();
}
private static void ExpressionSetPropertyStatic(Type type, string property, object value)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (property is null)
throw new ArgumentNullException(nameof(property));
if (value is null)
throw new ArgumentNullException(nameof(value));
var propertyInfo = type.GetProperty(property);
var argumentParam = Expression.Parameter(typeof(Object));
var convExpr = Expression.Convert(argumentParam, propertyInfo.PropertyType);
var callExpr = Expression.Call(propertyInfo.GetSetMethod(), convExpr);
var expression = Expression.Lambda<Action<object>>(callExpr, argumentParam).Compile();
expression(value);
}
// --------------------------- Get and set property using expression in instance mode ---------------------------
private static object ExpressionGetPropertyInstance<T>(T instance, string property)
{
if (instance is null)
throw new ArgumentNullException(nameof(instance));
if (property is null)
throw new ArgumentNullException(nameof(property));
var type = instance.GetType();
var propertyInfo = type.GetProperty(property);
var instanceParam = Expression.Parameter(type);
var callExpr = Expression.Call(instanceParam, propertyInfo.GetGetMethod());
var convExpr = Expression.Convert(callExpr, typeof(Object));
var expression = Expression.Lambda<Func<T, Object>>(convExpr, instanceParam).Compile();
return expression(instance);
}
private static void ExpressionSetPropertyInstance<T>(T instance, string property, object value)
{
if (instance is null)
throw new ArgumentNullException(nameof(instance));
if (property is null)
throw new ArgumentNullException(nameof(property));
if (value is null)
throw new ArgumentNullException(nameof(value));
var type = instance.GetType();
var propertyInfo = type.GetProperty(property);
var instanceParam = Expression.Parameter(type);
var argumentParam = Expression.Parameter(typeof(Object));
var convExpr = Expression.Convert(argumentParam, propertyInfo.PropertyType);
var callExpr = Expression.Call(instanceParam, propertyInfo.GetSetMethod(), convExpr);
var expression = Expression.Lambda<Action<T, object>>(callExpr, instanceParam, argumentParam).Compile();
expression(instance, value);
}
// --------------------------- Get and set field using expression in static mode ---------------------------
private static object ExpressionGetFieldStatic(Type type, string field)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (field is null)
throw new ArgumentNullException(nameof(field));
var fieldInfo = type.GetField(field);
var assignExpr = Expression.Field(null, fieldInfo.DeclaringType, fieldInfo.Name);
var convExpr = Expression.Convert(assignExpr, typeof(object));
var expression = Expression.Lambda<Func<object>>(convExpr).Compile();
return expression();
}
private static void ExpressionSetFieldStatic(Type type, string field, object value)
{
if (type is null)
throw new ArgumentNullException(nameof(type));
if (field is null)
throw new ArgumentNullException(nameof(field));
if (value is null)
throw new ArgumentNullException(nameof(value));
var fieldInfo = type.GetField(field);
var argumentParam = Expression.Parameter(typeof(object));
var assignExpr = Expression.Field(null, fieldInfo.DeclaringType, fieldInfo.Name);
var convertExpr = Expression.Convert(argumentParam, assignExpr.Type);
var setExpr = Expression.Assign(assignExpr, convertExpr);
var expression = Expression.Lambda<Action<object>>(setExpr, argumentParam).Compile();
expression(value);
}
// --------------------------- Get and set field using expression in instance mode ---------------------------
private static object ExpressionGetFieldInstance<T>(T instance, string field)
{
if (instance is null)
throw new ArgumentNullException(nameof(instance));
if (field is null)
throw new ArgumentNullException(nameof(field));
var type = instance.GetType();
var fieldInfo = type.GetField(field);
var instanceParam = Expression.Parameter(type);
var assignExpr = Expression.Field(instanceParam, fieldInfo);
var convExpr = Expression.Convert(assignExpr, typeof(object));
var expression = Expression.Lambda<Func<T, object>>(convExpr, instanceParam).Compile();
return expression(instance);
}
private static void ExpressionSetFieldInstance<T>(T instance, string field, object value)
{
if (instance is null)
throw new ArgumentNullException(nameof(instance));
if (field is null)
throw new ArgumentNullException(nameof(field));
if (value is null)
throw new ArgumentNullException(nameof(value));
var type = instance.GetType();
var fieldInfo = type.GetField(field);
var instanceParam = Expression.Parameter(type);
var argumentParam = Expression.Parameter(typeof(object));
var convExpr = Expression.Convert(argumentParam, fieldInfo.FieldType);
var assignExpr = Expression.Field(instanceParam, fieldInfo);
var setExpr = Expression.Assign(assignExpr, convExpr);
var expression = Expression.Lambda<Action<T, object>>(setExpr, instanceParam, argumentParam).Compile();
expression(instance, value);
}
// --------------------------- CUT HERE ---------------------------
public static void Main()
{
Console.WriteLine("---------- Static set/get using expression on properties ----------");
Console.WriteLine($"Person name before set: {Person.Name}");
Console.WriteLine($"Person name using exp: {ExpressionGetPropertyStatic(typeof(Person), "Name")}");
ExpressionSetPropertyStatic(typeof(Person), "Name", "Trevor");
Console.WriteLine($"Person name after set: {Person.Name}");
Console.WriteLine($"Person name using exp: {ExpressionGetPropertyStatic(typeof(Person), "Name")}");
Console.WriteLine();
Console.WriteLine("---------- Instance set/get using expression on properties ----------");
var aid = new App();
Console.WriteLine($"App name before set: {aid.Name}");
Console.WriteLine($"App name using exp: {ExpressionGetPropertyInstance(aid, "Name")}");
ExpressionSetPropertyInstance(aid, "Name", "Mastodon");
Console.WriteLine($"App name after set: {aid.Name}");
Console.WriteLine($"App name using exp: {ExpressionGetPropertyInstance(aid, "Name")}");
Console.WriteLine();
Console.WriteLine("---------- Static set/get using expression on fields ----------");
Console.WriteLine($"Person name before set: {Person.Title}");
Console.WriteLine($"Person name using exp: {ExpressionGetFieldStatic(typeof(Person), "Title")}");
ExpressionSetFieldStatic(typeof(Person), "Title", "Fabrikam CEO");
Console.WriteLine($"Person name after set: {Person.Title}");
Console.WriteLine($"Person name using exp: {ExpressionGetFieldStatic(typeof(Person), "Title")}");
Console.WriteLine();
Console.WriteLine("---------- Instance set/get using expression on fields ----------");
Console.WriteLine($"App name before set: {aid.Desc}");
Console.WriteLine($"App name using exp: {ExpressionGetFieldInstance(aid, "Desc")}");
ExpressionSetFieldInstance(aid, "Desc", "Decentralized social network");
Console.WriteLine($"App name after set: {aid.Desc}");
Console.WriteLine($"App name using exp: {ExpressionGetFieldInstance(aid, "Desc")}");
Console.WriteLine();
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment