add a new Party.EnsureStaticBindings method - read HISTORY.md

This commit is contained in:
Gerasimos (Makis) Maropoulos 2022-03-12 12:32:27 +02:00
parent 7ab0f6fff5
commit 9cf6f9fa5e
No known key found for this signature in database
GPG Key ID: 66FCC29BD385FCA6
6 changed files with 26 additions and 0 deletions

View File

@ -28,6 +28,8 @@ The codebase for Dependency Injection, Internationalization and localization and
## Fixes and Improvements ## Fixes and Improvements
- Add `Party.EnsureStaticBindings` which, if called, the MVC binder panics if a struct's input binding depends on the HTTP request data instead of a static dependency. This is useful to make sure your API crafted through `Party.PartyConfigure` depends only on struct values you already defined at `Party.RegisterDependency` == will never use reflection at serve-time (maximum performance).
- Add a new [x/sqlx](/x/sqlx/) sub-package ([example](_examples/database/sqlx/main.go)). - Add a new [x/sqlx](/x/sqlx/) sub-package ([example](_examples/database/sqlx/main.go)).
- Add a new [x/reflex](/x/reflex) sub-package. - Add a new [x/reflex](/x/reflex) sub-package.

View File

@ -16,6 +16,7 @@ This example contains only the basics, however, the library supports rooms, nati
Open a terminal window instance and execute: Open a terminal window instance and execute:
```sh ```sh
$ go mod tidy -compat=1.17
$ go run server.go # start the websocket server. $ go run server.go # start the websocket server.
``` ```
@ -25,6 +26,7 @@ Start a new terminal instance and execute:
```sh ```sh
$ cd ./go-client $ cd ./go-client
$ go mod tidy -compat=1.17
$ go run client.go # start the websocket client. $ go run client.go # start the websocket client.
# start typing... # start typing...
``` ```

View File

@ -339,6 +339,15 @@ func (api *APIBuilder) ConfigureContainer(builder ...func(*APIContainer)) *APICo
return api.apiBuilderDI return api.apiBuilderDI
} }
// EnsureStaticBindings panics on struct handler (controller)
// if at least one input binding depends on the request and not in a static structure.
// Should be called before `RegisterDependency`.
func (api *APIBuilder) EnsureStaticBindings() Party {
diContainer := api.ConfigureContainer()
diContainer.Container.DisableStructDynamicBindings = true
return api
}
// RegisterDependency calls the `ConfigureContainer.RegisterDependency` method // RegisterDependency calls the `ConfigureContainer.RegisterDependency` method
// with the provided value(s). See `HandleFunc` and `PartyConfigure` methods too. // with the provided value(s). See `HandleFunc` and `PartyConfigure` methods too.
func (api *APIBuilder) RegisterDependency(dependencies ...interface{}) { func (api *APIBuilder) RegisterDependency(dependencies ...interface{}) {

View File

@ -27,6 +27,10 @@ type Party interface {
// //
// It returns the same `APIBuilder` featured with Dependency Injection. // It returns the same `APIBuilder` featured with Dependency Injection.
ConfigureContainer(builder ...func(*APIContainer)) *APIContainer ConfigureContainer(builder ...func(*APIContainer)) *APIContainer
// EnsureStaticBindings panics on struct handler (controller)
// if at least one input binding depends on the request and not in a static structure.
// Should be called before `RegisterDependency`.
EnsureStaticBindings() Party
// RegisterDependency calls the `ConfigureContainer.RegisterDependency` method // RegisterDependency calls the `ConfigureContainer.RegisterDependency` method
// with the provided value(s). See `HandleFunc` and `PartyConfigure` methods too. // with the provided value(s). See `HandleFunc` and `PartyConfigure` methods too.
RegisterDependency(dependencies ...interface{}) RegisterDependency(dependencies ...interface{})

View File

@ -53,6 +53,10 @@ type Container struct {
// set to true to disable that kind of behavior. // set to true to disable that kind of behavior.
DisablePayloadAutoBinding bool DisablePayloadAutoBinding bool
// DisableStructDynamicBindings if true panics on struct handler (controller)
// if at least one input binding depends on the request and not in a static structure.
DisableStructDynamicBindings bool
// DependencyMatcher holds the function that compares equality between // DependencyMatcher holds the function that compares equality between
// a dependency with an input. Defaults to DefaultMatchDependencyFunc. // a dependency with an input. Defaults to DefaultMatchDependencyFunc.
DependencyMatcher DependencyMatcher DependencyMatcher DependencyMatcher
@ -249,6 +253,7 @@ func (c *Container) Clone() *Container {
copy(clonedDeps, c.Dependencies) copy(clonedDeps, c.Dependencies)
cloned.Dependencies = clonedDeps cloned.Dependencies = clonedDeps
cloned.DisablePayloadAutoBinding = c.DisablePayloadAutoBinding cloned.DisablePayloadAutoBinding = c.DisablePayloadAutoBinding
cloned.DisableStructDynamicBindings = c.DisableStructDynamicBindings
cloned.MarkExportedFieldsAsRequired = c.MarkExportedFieldsAsRequired cloned.MarkExportedFieldsAsRequired = c.MarkExportedFieldsAsRequired
cloned.resultHandlers = c.resultHandlers cloned.resultHandlers = c.resultHandlers
// Reports are not cloned. // Reports are not cloned.

View File

@ -71,6 +71,10 @@ func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Stru
elem.FieldByIndex(b.Input.StructFieldIndex).Set(input) elem.FieldByIndex(b.Input.StructFieldIndex).Set(input)
} else if !b.Dependency.Static { } else if !b.Dependency.Static {
if c.DisableStructDynamicBindings {
panic(fmt.Sprintf("binder: DisableStructDynamicBindings setting is set to true: dynamic binding found: %s", b.String()))
}
singleton = false singleton = false
} }
} }