Add StuntReference, Stunt.For/Get and StuntBuilder - #252
Merged
Merged
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adds two related ways to configure stunt behaviors beyond the bare
Stunt.Of<T>.StuntReference<T>/Stunt.For/Stunt.GetStunt.For<T>(...)returns aStuntReference<T>that implementsIStunt, soAddBehavior/InsertBehaviorapply to it directly and the concrete type flows through for chaining. The stunt is not constructed until the firstToObject()(the implicit conversion callsToObject()too). That call installs the behaviors configured so far withBehaviorPipelineFactory.UseAmbient, so virtual members invoked from a base constructor are intercepted. If none were added, the factory already current at that call is used. After construction,Behaviorsforwards to the stunt's own pipeline.Stunt.Get(stunt)still wraps an already created stunt and forwardsBehaviorsimmediately.An implicit conversion to
Tis declared too, but C# does not allow user-defined conversions to interface types, so it only applies to class and delegate stunts, which is whyStunt.Of<T>keeps returningT.Behaviors configured before
ToObject()also see the constructor invocation itself. A behavior that only understands a particular method should skip constructors (appliesTo) or callnext.StuntBuilderStunt.Builder()returns aStuntBuilderthat collects behaviors (sameAddBehavior/InsertBehaviorextension methods, since it implementsIStunt) and applies them to every stunt it builds. ItsBuild<T>overloads mirrorStunt.Of<T>one to one, including the delegate overload and theT1..T8extra interfaces.Each
Buildwraps creation inBehaviorPipelineFactory.UseAmbientwith a factory that seeds the new pipeline from the builder behaviors, so the same behaviors apply during construction of every stunt the builder creates.BehaviorPipelinecopies the enumerable it is given, so every built stunt gets a snapshot of the behaviors at build time while sharing the behavior instances (a singleRecordingBehaviorrecords all stunts from that builder).Notes
Of,For,Build) carries[StuntGenerator], which is what the source generator keys off to decide which stunt types to generate from the call site's type arguments. This works for instance methods too, sobuilder.Build<T>()participates in compile-time generation.src/Stunts.Package/Stunt.vbmirrors the C# content file. VB cannot constrain a type parameter toSystem.Delegate(BC32061), so the delegate overloads are unconstrained; behavior is identical. There is no VB project in the solution, so the file was validated by compiling it in a scratchOption Strict Onproject againstStunts.dll.src/Stunts.UnitTests/Scenarios/StuntBuilder.csand a class-proxy scenario that configures a behavior onStunt.ForbeforeToObject().readme.mdandAGENTS.mddocument the API and the design decisions.