Skip to content

Commit 9f53d15

Browse files
committed
minor changes to MVC, see HISTORY.md#Next for more
1 parent 79404f9 commit 9f53d15

File tree

4 files changed

+43
-4
lines changed

4 files changed

+43
-4
lines changed

HISTORY.md

+6
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ Developers are not forced to upgrade if they don't really need it. Upgrade whene
2323

2424
Changes apply to `main` branch.
2525

26+
- Add optional `Singleton() bool` method to controllers to mark them as singleton, will panic with a specific error if a controller expects dynamic dependencies. This behavior is idendical to the app-driven `app.EnsureStaticBindings()`.
27+
28+
- Non-zero fields of a controller that are marked as ignored, with `ignore:"true"` field tag, they are not included in the dependencies at all now.
29+
30+
- Re-add error log on context rich write (e.g. JSON) failures when the application is running under debug mode (with `app.Logger().SetLevel("debug")`) and there is no a registered context error handler at place.
31+
2632
- `master` branch finally renamed to `main`. Don't worry GitHub will still navigate any `master` request to `main` automatically. Examples, Documentation and other Pages are refactored too.
2733

2834
# Sat, 12 Aug 2023 | v12.2.4

context/context.go

+5-2
Original file line numberDiff line numberDiff line change
@@ -4213,6 +4213,9 @@ func (ctx *Context) handleContextError(err error) {
42134213
if errHandler := ctx.app.GetContextErrorHandler(); errHandler != nil {
42144214
errHandler.HandleContextError(ctx, err)
42154215
} else {
4216+
if ctx.IsDebug() {
4217+
ctx.app.Logger().Error(err)
4218+
}
42164219
ctx.StatusCode(http.StatusInternalServerError)
42174220
}
42184221

@@ -4258,8 +4261,8 @@ func (ctx *Context) JSON(v interface{}, opts ...JSON) (err error) {
42584261
}
42594262

42604263
if err = ctx.writeJSON(v, options); err != nil {
4261-
// if no options are given or OmitErrorHandler is true
4262-
// then do call the error handler (which may lead to a cycle).
4264+
// if no options are given or OmitErrorHandler is false
4265+
// then call the error handler (which may lead to a cycle if the error handler fails to write JSON too).
42634266
if !options.OmitErrorHandler {
42644267
ctx.handleContextError(err)
42654268
}

hero/reflect.go

+3
Original file line numberDiff line numberDiff line change
@@ -201,6 +201,9 @@ func lookupFields(elem reflect.Value, skipUnexported bool, onlyZeros bool, paren
201201
func lookupNonZeroFieldValues(elem reflect.Value) (nonZeroFields []reflect.StructField) {
202202
fields, _ := lookupFields(elem, true, false, nil)
203203
for _, f := range fields {
204+
if structFieldIgnored(f) {
205+
continue // re-check here for ignored struct fields so we don't include them on dependencies. Non-zeroes fields can be static, even if they are functions.
206+
}
204207
if fieldVal := elem.FieldByIndex(f.Index); goodVal(fieldVal) && !isZero(fieldVal) {
205208
/* && f.Type.Kind() == reflect.Ptr &&*/
206209
nonZeroFields = append(nonZeroFields, f)

hero/struct.go

+29-2
Original file line numberDiff line numberDiff line change
@@ -43,15 +43,38 @@ type Struct struct {
4343
Singleton bool
4444
}
4545

46+
type singletonStruct interface {
47+
Singleton() bool
48+
}
49+
50+
func isMarkedAsSingleton(structPtr any) bool {
51+
if sing, ok := structPtr.(singletonStruct); ok && sing.Singleton() {
52+
return true
53+
}
54+
55+
return false
56+
}
57+
4658
func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Struct {
4759
v := valueOf(structPtr)
4860
typ := v.Type()
4961
if typ.Kind() != reflect.Ptr || indirectType(typ).Kind() != reflect.Struct {
5062
panic("binder: struct: should be a pointer to a struct value")
5163
}
5264

65+
isSingleton := isMarkedAsSingleton(structPtr)
66+
67+
disablePayloadAutoBinding := c.DisablePayloadAutoBinding
68+
enableStructDependents := c.EnableStructDependents
69+
disableStructDynamicBindings := c.DisableStructDynamicBindings
70+
if isSingleton {
71+
disablePayloadAutoBinding = true
72+
enableStructDependents = false
73+
disableStructDynamicBindings = true
74+
}
75+
5376
// get struct's fields bindings.
54-
bindings := getBindingsForStruct(v, c.Dependencies, c.MarkExportedFieldsAsRequired, c.DisablePayloadAutoBinding, c.EnableStructDependents, c.DependencyMatcher, partyParamsCount, c.Sorter)
77+
bindings := getBindingsForStruct(v, c.Dependencies, c.MarkExportedFieldsAsRequired, disablePayloadAutoBinding, enableStructDependents, c.DependencyMatcher, partyParamsCount, c.Sorter)
5578

5679
// length bindings of 0, means that it has no fields or all mapped deps are static.
5780
// If static then Struct.Acquire will return the same "value" instance, otherwise it will create a new one.
@@ -73,14 +96,18 @@ func makeStruct(structPtr interface{}, c *Container, partyParamsCount int) *Stru
7396

7497
elem.FieldByIndex(b.Input.StructFieldIndex).Set(input)
7598
} else if !b.Dependency.Static {
76-
if c.DisableStructDynamicBindings {
99+
if disableStructDynamicBindings {
77100
panic(fmt.Sprintf("binder: DisableStructDynamicBindings setting is set to true: dynamic binding found: %s", b.String()))
78101
}
79102

80103
singleton = false
81104
}
82105
}
83106

107+
if isSingleton && !singleton {
108+
panic(fmt.Sprintf("binder: Singleton setting is set to true but struct has dynamic bindings: %s", typ))
109+
}
110+
84111
s := &Struct{
85112
ptrValue: v,
86113
ptrType: typ,

0 commit comments

Comments
 (0)