A word of advice, if you are not using an IoC, you don't have the problem of defining components, you have the one before that, of dependency management. I am talking here what happens after you embrace IoC, what the next pain points are.
Having the configuration in a single place, being able to define both the shape of the application and its configuration is really nice. It makes a lot of things very easy. Until you want to send allow the user to extend a single facet of the configuration, but not allow them (or not expose them) to the full configuration.
You would want to define your components in a single place, and their configuration in another. To supply all the required configuration, and let the end user override them.
That is usually the place where we setup bridge to a more traditional configuration approaches, which isn't really pleasant. I just added to Binsor to do this across files, so I can use the following syntax to define and override configuration.
Main file:
def DefineComponent():
component "email_sender", ISender, EmailSender
component "email_sender2", ISender, EmailSender:
Host = "example123.dot.org", To = ( "Lauren" )
component "email_sender3", ISender, EmailSender
Extensibility file:
import file from Main.boo
DefineComponent()
extend "email_sender":
Host = "example.dot.org", To = ( "Kaitlyn", "Matthew", "Lauren" )
extend "email_sender2":
Host = "example.dot.org", To = ( "Kaitlyn", "Matthew", "Lauren" )
extend "email_sender3":
@startable = true
@tag1 = "important", tag2 = "priority"
lifestyle Pooled, InitialPoolSize = 10, MaxPoolSize = 100
configuration:
hosts(list, item: host) = ["rhino", "orca"]
Combine that with the Windsor's resource system, and you get an embedded configuration, externally configurable.
I find it very sleek.