Basic Concepts

Why ToGPALObject()

Two Ways to Finish a Chain

Using ToGPALObject() at the end of a chain and casting the result explicitly to the concrete type are two ways to do the same thing. Each With... Call in the chain returns a configuration interface that only exposes more With... Methods -- it is not the finished object. ToGPALObject() or an explicit cast is what converts that configuration into the real, usable object with all of its members available.

// These two lines are equivalent

Selector sel1 = GPAL.Selector.WithCSS("#username").ToGPALObject();

Selector sel1 = (Selector)GPAL.Selector.WithCSS("#username");

NOTE

If you stop at GPAL.Selector.WithCSS("#username") without ToGPALObject() or a cast, the result is still just the configuration interface. Var sel1 = GPAL.Selector.WithCSS("#username"); compiles, but sel1's type only offers more With... Methods. Calling sel1.Remove() on it will not compile. ToGPALObject() or a cast is what gets you the rest of the object's API.

Picking One: Declared Variables vs Inline Arguments

When declaring a variable, ToGPALObject() is usually easier. IntelliSense offers it right at the end of the chain with no need to remember the exact type name. When passing a chain inline as an argument, an explicit cast can read cleaner: the type name up front signals what is being handed over without a trailing ToGPALObject() at the end of a long chain.

// Inline argument - explicit cast reads cleanly

GPAL.Form

.WithTitle("Confirm Action")

.WithFormControl((Button)GPAL.Button

.WithText("Proceed")

.WithCallback<EventHandler>(SaveButton_Click)

.ForEvent(ControlEventType.Click))

.ShowDialog();


// Same control, written with ToGPALObject() instead

GPAL.Form

.WithTitle("Confirm Action")

.WithFormControl(GPAL.Button

.WithText("Proceed")

.WithCallback<EventHandler>(SaveButton_Click)

.ForEvent(ControlEventType.Click)

.ToGPALObject())

.ShowDialog();

NOTE

GPAL doesn't enforce either style. Both compile to the same thing. Pick based on what reads best for that line: ToGPALObject() while writing a chain top to bottom, an explicit cast when the chain is just one argument among several.

A Third Option: dynamic for Reference Storage

When you only need to store a reference to call methods on later -- and you do not need compile-time type checking on that variable -- declaring it as dynamic sidesteps the need for ToGPALObject() or an explicit cast entirely. The assignment resolves at runtime and every method call on the dynamic variable dispatches to the actual underlying object. This works well for browser or application references stored as fields and called from event handlers. It does not work for form controls, where you need the concrete typed field to pass to WithFormControl and other typed parameters.

// dynamic: no ToGPALObject or cast needed, resolved at runtime

static dynamic browser { get; set; }


browser = GPAL.Browser

.WithUseAutomationEngine(AutomationEngine.PuppeteerPort)

.GoTo("https://example.com");


// later, in another handler:

browser?.Close();


// For controls, you still need the concrete type --

// WithFormControl requires GPALButton, not dynamic

static GPALButton saveBtn = GPAL.Button

.WithText("Save")

.WithName("saveBtn")

.ToGPALObject();

NOTE

Use dynamic when you need to store a GPAL object reference and call methods on it later, but the exact return type is inconvenient to spell out or changes across calls. Use ToGPALObject() or an explicit cast when you need the typed API -- for passing to WithFormControl, for IntelliSense on the variable, or when the type will be inspected at compile time.

💬 Ask GPAL