Skip to content

Instantly share code, notes, and snippets.

@leandromoh
Created June 9, 2020 15:00
Show Gist options
  • Save leandromoh/d81d8ad17f34d10c5b5d0ed5ac13fe87 to your computer and use it in GitHub Desktop.
Save leandromoh/d81d8ad17f34d10c5b5d0ed5ac13fe87 to your computer and use it in GitHub Desktop.
Anonymous extension method that allow create a new instance of anonymous with new values, similar to with expression of records in C# and F#
public static class AnonymousExtension
{
static void Main(string[] args)
{
var person = new { FirstName = "Scott", LastName = "Hunter", Sex = 'M', Age = 25 };
var otherPerson = person.With(new { LastName = "Hanselman" });
Console.WriteLine(otherPerson);
}
public static T With<T, U>(this T x, U y)
{
return AnonymousHelper<T, U>.Create(x, y);
}
private static class AnonymousHelper<T, U>
{
public static readonly Func<T, U, T> Create;
static AnonymousHelper()
{
ParameterExpression x = Expression.Variable(typeof(T), "x");
ParameterExpression y = Expression.Variable(typeof(U), "y");
var ctr = typeof(T).GetConstructors()[0];
var values = ctr.GetParameters()
.Select(p =>
{
var instance = typeof(U).GetProperty(p.Name, p.ParameterType) is null ? x : y;
return Expression.Property(instance, p.Name);
});
var exp = Expression.New(ctr, values);
var lam = Expression.Lambda<Func<T, U, T>>(exp, new[] { x, y });
Create = lam.Compile();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment