{"action":"created","issue":{"url":"https://api.github.com/repos/Swinject/Swinject/issues/35","labels_url":"https://api.github.com/repos/Swinject/Swinject/issues/35/labels{/name}","comments_url":"https://api.github.com/repos/Swinject/Swinject/issues/35/comments","events_url":"https://api.github.com/repos/Swinject/Swinject/issues/35/events","html_url":"https://github.com/Swinject/Swinject/issues/35","id":120939700,"number":35,"title":"Proposal for modular assembly of services in container","user":{"login":"mowens","id":4575216,"avatar_url":"https://avatars.githubusercontent.com/u/4575216?v=3","gravatar_id":"","url":"https://api.github.com/users/mowens","html_url":"https://github.com/mowens","followers_url":"https://api.github.com/users/mowens/followers","following_url":"https://api.github.com/users/mowens/following{/other_user}","gists_url":"https://api.github.com/users/mowens/gists{/gist_id}","starred_url":"https://api.github.com/users/mowens/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/mowens/subscriptions","organizations_url":"https://api.github.com/users/mowens/orgs","repos_url":"https://api.github.com/users/mowens/repos","events_url":"https://api.github.com/users/mowens/events{/privacy}","received_events_url":"https://api.github.com/users/mowens/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":3,"created_at":"2015-12-08T06:13:01Z","updated_at":"2015-12-08T16:23:09Z","closed_at":null,"body":"# Proposal for modular assembly of services in container\r\nProvide a simple mechanism to populate service definitions in a container that allows implementations to group related components together across frameworks/application\r\n\r\nThe current implementation has no opinion to how services are registered to the container which allows users to assembly their container(s) however you want. This is all well and good, but it would be nice to provide consumers of the framework an opinionated way to register their services. My proposal is to provide an `AssemblyType` and `Assembler` to provide such a feature. This approach would allow sane bootstrapping of the container (this concept is taking from is very vaguely taken from [Typhoon](https://github.com/appsquickly/Typhoon/wiki/Modularizing-Assemblies)\r\n\r\n## Proposed Implementation\r\nThere are 2 components to the implementation: `AssemblyType` and `Assembler`. The `AssemblyType` provides an interface that can be implemented by classes/structs (depending on your use case) that is provided a container from elsewhere.\r\n\r\n```\r\nprotocol AssemblyType {\r\n    func assemble(container: Container)\r\n}\r\n```\r\n\r\nThe `Assembler` will take a list of `AssemblyType` instances and build the container. The `Assembler` will either:\r\na) Own the container\r\nb) Create the container to be owned else where\r\n\r\nThe implementation would be really straight forward:\r\n\r\n```\r\nclass Assembler {\r\n   let container = Container()\r\n   init(assemblies: [AssemblyType]) {\r\n       for assembly in assemblies {\r\n           assembly.assemble(container)\r\n       }\r\n   }\r\n}\r\n```\r\n\r\nWith this approach, one can separate their service definitions like so:\r\n\r\n```\r\nclass ServiceAssembly: AssemblyType {\r\n    func assemble(container: Container) {\r\n        container.register(FooServiceType.self) { r in \r\n             FooService() \r\n        }\r\n        container.register(BarServiceType.self) { r in \r\n            BarService() \r\n        }\r\n    }\r\n}\r\n\r\nclass ManagerAssembly: AssemblyType {\r\n    func assemble(container: Container) {\r\n        container.register(FooManagerType.self) { r in \r\n            FooManager(service: r.resolve(FooServiceType.self)!)\r\n        }\r\n        container.register(BarManagerType.self) { r in \r\n             BarManager(service: r.resolve(BarServiceType.self)!) \r\n        }\r\n    }\r\n}\r\n```\r\nNow like service definitions are grouped and we can build our container like so:\r\n```\r\nlet assembler = Assembler(assemblies: [\r\n    ServiceAssembly(),\r\n    ManagerAssembly()\r\n])\r\nlet container = assembler.container // will contain all registered services\r\n```\r\n\r\nAdditionally, this provides an easy means to override service definitions with mocks using inheritance. Let's say we want to replace `FooService` with `MockFooService`:\r\n\r\n```\r\nclass MockServiceAssembly: ServiceAssembly {\r\n    override func assemble(container: Container) {\r\n        super.assemble(container)\r\n        \r\n        container.register(FooServiceType.self) { r in \r\n             MockFooService() \r\n        }\r\n    }\r\n}\r\n```\r\n\r\nThen we would load our assembler with the `MockServiceAssembly` instead:\r\n```\r\nlet assembler = Assembler(assemblies: [\r\n    MockServiceAssembly(),\r\n    ManagerAssembly()\r\n])\r\n```"},"comment":{"url":"https://api.github.com/repos/Swinject/Swinject/issues/comments/162934714","html_url":"https://github.com/Swinject/Swinject/issues/35#issuecomment-162934714","issue_url":"https://api.github.com/repos/Swinject/Swinject/issues/35","id":162934714,"user":{"login":"yoichitgy","id":965994,"avatar_url":"https://avatars.githubusercontent.com/u/965994?v=3","gravatar_id":"","url":"https://api.github.com/users/yoichitgy","html_url":"https://github.com/yoichitgy","followers_url":"https://api.github.com/users/yoichitgy/followers","following_url":"https://api.github.com/users/yoichitgy/following{/other_user}","gists_url":"https://api.github.com/users/yoichitgy/gists{/gist_id}","starred_url":"https://api.github.com/users/yoichitgy/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/yoichitgy/subscriptions","organizations_url":"https://api.github.com/users/yoichitgy/orgs","repos_url":"https://api.github.com/users/yoichitgy/repos","events_url":"https://api.github.com/users/yoichitgy/events{/privacy}","received_events_url":"https://api.github.com/users/yoichitgy/received_events","type":"User","site_admin":false},"created_at":"2015-12-08T16:23:08Z","updated_at":"2015-12-08T16:23:08Z","body":"Thanks Mike. now I'm confident to go with the single repo. I'm going to start renaming the source and test directories to try SPM. I won't make submodule directories for now to see more new information or discovery about SPM.\r\n\r\nYou can implement the assembly feature without modifying the existing code, can't you? Just to prepare the submodule layout in the future. I think, even if something should be added to `Container`, it can be implemented in a new file with an extension to `Container`.\r\n\r\nI am curious to see the Objc things too. We should watch. Another curiosity is Apple has decided to implement Foundation in Swift. (Core)Foundation was implemented in C with toll free bridge to Objective-C. Probably UIKit will replace its dependency on CoreFoundation to Swift Foundation."}}