QRCoder
QRCoder copied to clipboard
[WIP/QRCoder2] Fluent API experimentation PR
Summary
Experimentation with fluent API syntax
Samples
var code = QRCodeBuilder.CreateEmail("[email protected]")
.WithSubject("Testing")
.WithBody("Hello World!")
.WithErrorCorrection(QRCodeGenerator.ECCLevel.H)
.RenderWith<AsciiRenderer>()
.WithQuietZone(false)
.ToString();
var image = QRCodeBuilder.CreatePhoneNumber("1234567890")
.WithErrorCorrection(QRCodeGenerator.ECCLevel.H)
.RenderWith<SystemDrawingRenderer>(20)
.WithQuietZone(false)
.ToBitmap();
var base64 = QRCodeBuilder.CreateMMS("1234567890", "Hello")
.RenderWith<PngRenderer>()
.ToBase64String();
Intellisense samples
Preliminary Findings
- Could start with
new QRCodeBuilder.Email("[email protected]")rather thanQRCodeBuilder.CreateEmail("[email protected]")- which is pretty similar to the existingnew PayloadGenerator.Wifi()syntax actually, with the difference being the fluent syntax for configuration. One benefit of usingnewis that additional payloads can be added by simply adding a new class into the correct namespace. Whereas methods cannot be added toQRCodeBuilderoutside of QRCoder. - Using
RenderWith<T>breaks the intellisense pattern because T does not give a list of the specific renderers available. Probably better to create an extension method for each renderer, likeRenderAsAscii()andRenderAsPng(20)instead RenderWith<T>does not allow for render-specific constructor parameters. I've compensated with support for only two patterns: (1) no arguments (2) pixels per module argument. HavingRenderAs...()dedicated methods would allow each renderer to require specific arguments.- The builder syntax could likely be added to v1.x as a new layer, as shown in this PR, with any implementation changes we wish to make within the builder methods. Then v2 just removes (or makes internal) all the old methods.
- The new builders, when layered on the old code, are quite easy to write. Once the old code is removed, additional optimizations can be added to enhance trimming support. This trimming capability may consolidate the QRCode and ArtQRCode classes.
- All of the supporting code can be nested as deep within namespaces as desired, since intellisense always provides the correct context-sensitive methods. Except for
RenderWith<T>, as noted in item 2 above. Another reason to useRenderAsAscii()or similar. - The extension methods on the renderers (
ToArray,ToStream,ToFile, etc) are really cool -- each renderer need only implementToStreamand all the other methods are available via extension methods. Similar functionality for text renderers; even with only implementingToStringthey can also provideToFile,ToStream,ToBase64, and so on via extension methods.
The builder syntax could likely be added to v1.x as a new layer, as shown in this PR
QRCoder2.FluentExtensions maybe? š
Hi Shane, thanks for the PR. That looks pretty interesting. However, I don't want to merge this into v1.x, but would like to include it in v2 first, as I don't want to make/document/communicate any more major API changes to v1. I hope that's okay with you.
Certainly. I wrote this more of a discussion/preview/review of a potential approach.
Hi @Shane32 ,
since QRCoder will reach its end of life and the repository will be archived on November 1st, 2025, Iād like to clarify how to proceed with this PR.
Would you prefer me to merge it before the archival, or should I close it instead?
Please let me know what you think ā I want to handle your contribution in the way that feels most appropriate to you.
Thanks again for your effort and contribution!
Closed in consultation with @Shane32