@@ -59,6 +59,7 @@ type Container interface {
5959 AllowCircularReferences ()
6060 Object (i interface {}) * BeanDefinition
6161 Provide (ctor interface {}, args ... arg.Arg ) * BeanDefinition
62+ Configuration (i interface {}) * BeanDefinition
6263 Refresh () error
6364 Close ()
6465}
@@ -187,6 +188,81 @@ func (c *container) AllowCircularReferences() {
187188 c .allowCircularReferences = true
188189}
189190
191+ // Configuration scan that the object `i` has `NewXXX` methods to Ioc container.
192+ //
193+ // example:
194+ //
195+ // func(x *T) NewFoo() *Foo
196+ //
197+ // func(x *T) NewBar(foo *Foo) *Bar
198+ //
199+ // func(x *T) NewSubject(bar *Bar) (*Subject, error)
200+ //
201+ // func(x *T) NewServer() *gs.BeanDefinition
202+ func (c * container ) Configuration (i interface {}) * BeanDefinition {
203+
204+ bValue := reflect .ValueOf (i )
205+ bType := bValue .Type ()
206+
207+ for j := 0 ; j < bType .NumMethod (); j ++ {
208+ method := bType .Method (j )
209+ if ! strings .HasPrefix (method .Name , "New" ) {
210+ continue
211+ }
212+
213+ switch method .Type .NumOut () {
214+ case 1 : // func(x *T) NewFoo() *Foo
215+ outType := method .Type .Out (0 )
216+ if ! utils .IsBeanType (outType ) {
217+ continue
218+ }
219+
220+ if outType == bdType {
221+ if method .Type .NumIn () != 1 {
222+ panic (fmt .Errorf ("non-parameter constructor required: %s" , method .Type .String ()))
223+ }
224+
225+ bdValues := method .Func .Call ([]reflect.Value {bValue })
226+ bdInst := bdValues [0 ].Interface ()
227+ c .Accept (bdInst .(* BeanDefinition ))
228+ } else {
229+ c .Provide (method .Func .Interface ())
230+ }
231+
232+ case 2 :
233+ out0Type := method .Type .Out (0 )
234+ if ! utils .IsBeanType (out0Type ) {
235+ continue
236+ }
237+
238+ out1Type := method .Type .Out (1 )
239+ if ! utils .IsErrorType (out1Type ) {
240+ panic (fmt .Errorf ("%s: second return type must be error" , method .Type .String ()))
241+ }
242+
243+ if out0Type == bdType {
244+ if method .Type .NumIn () != 1 {
245+ panic (fmt .Errorf ("non-parameter constructor required: %s" , method .Type .String ()))
246+ }
247+
248+ bdValues := method .Func .Call ([]reflect.Value {bValue })
249+ bdInst := bdValues [0 ].Interface ()
250+ bdErr := bdValues [1 ].Interface ()
251+ if err , ok := bdErr .(error ); ok && nil != err {
252+ panic (fmt .Errorf ("%s: %w" , method .Type .String (), err ))
253+ }
254+ c .Accept (bdInst .(* BeanDefinition ))
255+ } else {
256+ c .Provide (method .Func .Interface ())
257+ }
258+ }
259+
260+ // ignore other methods
261+ }
262+
263+ return c .Accept (NewBean (bValue ))
264+ }
265+
190266// Dependencies return the dependency order list in either ascending or descending order.
191267func (c * container ) Dependencies (asc bool ) (deps []* BeanDefinition ) {
192268 if ! asc {
0 commit comments