What tools/libraries exist that will take a struct and automatically generate an immutable wrapper and also a "builder" class for incrementally building new instances?
Example input:
struct Foo
{
public int apples;
public int oranges;
public Foo Clone() {return (Foo) base.MemberwiseClone();}
}
Example output:
public class ImmutableFoo // could probably be a struct
{
private Foo snapshot;
internal ImmutableFoo(Foo value) { this.snapshot = value; }
public FooBuilder Builder() { return new FooBuilder(snapshot); }
public int Apples { get { return snapshot.apples; } }
public int Oranges { get { return snapshot.oranges; } }
}
public class FooBuilder
{
private Foo state;
public int Apples { get { return state.apples; } set { state.apples = value; } }
public int Oranges { get { return state.oranges; } set { state.oranges = value; } }
public FooBuilder() { }
internal FooBuilder(Foo toCopy) { state = toCopy.Clone(); }
public ImmutableFoo Build()
{
ImmutableFoo result = new ImmutableFoo(state);
state = state.Clone();
return result;
}
}
Such a "tool" could be an IDE plugin or could generate the new class at run-time using reflection.
The example is in C# but I would be interested in a solution for any statically-typed OO language (Java, Scala, C++ etc.)
Desirable features:
- Re-creates methods from the struct in the builder class
- Re-creates nondestructive methods from the struct in the immutable class (esp.
Equals()
andGetHashCode()
and any interface methods) - Also generates a
IFooReader
interface containing read-only properties for each struct member, implemented by both the immutable and the builder. - If a field's class has an immutable equivalent, uses the immutable version in the immutable class (see also How do I create a builder in C# for an object that has properties that are referenc types?) e.g.
List
->ReadOnlyCollection
or similar. - Alternatively take the builder class as input (where the builder uses automatic properties instead of delegating to a struct.)
- Does not require the
Clone
method to be predefined
"You should not use a tool like this because..." answers are also welcome.