MelGrubb / BuilderGenerator

A source-generator-based implementation of the Builder pattern
https://melgrubb.github.io/BuilderGenerator/
MIT License
38 stars 8 forks source link

Fluent API enhancements #21

Open jvmlet opened 1 year ago

jvmlet commented 1 year ago

First of all, BIG thanks for the great library, having java background and getting used to Lombok, this functionality was really missing. Should be part of C# compiler ;-)

Suggestion :

  1. Having public abstract class Builder<T> where T : Builder<T> instead of public abstract class Builder<T> where T : class allows you to have fluent API by returning :
    public T  WithObject(T value)  {
      Object = new System.Lazy<T>(() => value);
      return (T)this; //safe cast to T
    }
  2. I would expect that WithObject(obj).WithSomethingElse(somethingElse).Build() will alter SomethingElse property of original object obj, but looking at generated BuilderGenerator.Builder , this doesn't behave like this. Would you please provide support for such use-case ? Maybe generating c'tor that gets obj :
    new ConcreteBuilder(obj).WithSomethingElse(somethingElse).Build() to be backward compatible and not interfere with .1 ?

Thanks again for your work,

MelGrubb commented 1 year ago

These builders work a little different than most. There's not an instance of an object behind the scenes that's being mutated. There are a series of lazy properties that then get applied when you finally tell it to build the final product. My builders are more like blueprints. However, I can see that by rearranging things slightly, they could move the "Object" to the head of the line and then apply the other properties after that, which might achieve what you're after. I'm in the middle of a performance and caching push these days, but I'll see what I can do.

jvmlet commented 1 year ago

Btw, protobuf generates obj.toBuilder() method ... Very similar to what Lombok does

MelGrubb commented 10 months ago

I know it's been a while, but I have a newer release for testing. v2.4.0-alpha introduces a constructor that takes in an example object. It copies the current properties in to the backing fields as well as setting the behind-the-scenes object to the one passed in. I think this covers the scenario you described. I'm still trying to decide on the final shape of things and write some more tests, but I thought you might be interested in checking out the alpha.

jvmlet commented 10 months ago

Great, thanks a lot.