I'd like to mimic the F# 'with' keyword (which can be used on records) in C#.
For now, when i create a new immutable class, I just add manually some custom "with" methods like this :
public class MyClass
{
public readonly string Name;
public readonly string Description;
public MyClass(string name, string description)
{
this.Name = name;
this.Description = description;
}
// Custom with methods
public MyClass WithName(string name)
{
return new MyClass(name, this.Description);
}
public MyClass WithDescription(string description)
{
return new MyClass(this.Name, description);
}
}
For my personal c# development, I tried to create a generic method to do this (in a perfect world, I would use F#). The "best" I did is something like :
public static class MyExtensions
{
public static TSource With<TSource, TField>(
this TSource obj,
string fieldName,
TField value)
where TSource : class
{
// Reflection stuff to use constructor with the new value
// (check parameters names and types)...
}
}
It works but I'm not quite satisfied because I lose compile time errors by using a string parameter (for now I don't care of performance issues).
I'd really like to be able to write something like the code below, where I replace the string parameter by a "projection" lambda :
var myClass1 = new MyClass("name", "desc");
var myClass2 = myClass1.With(obj => obj.Name, "newName");
My extension method would look something like :
public static TSource With<TSource, TField>(
this TSource obj,
Expression<Func<TSource, TField>> projection,
TField value)
where TSource : class
{
// TODO
}
So here are my questions :
- Is it possible to use reflection on the projection's result and get the field name from it ?
- Has someone else already done a robust "with" method in C# ?