Proposal for Library to perform dependency injection

Having had a career that has bounced me between a few languages, I have had the opportunity to work with a couple of tools in the Java world that didn't see, to have analogues in C++. One of these is the inversion of control containers, of which Spring is one of the best known. Ken Fowler suggested the term "Dependency Injection" as a way to better describe how inversion of control is performed, and I prefer his term. I've written a fairly simple dependency injection framework in C++ that seems to make proper use of the C++ Language. It is not attempting to do any COM like component model. Rather, it allows the developer the ability to cleanly separate the Object usage from the construction policy. I've posted the code on Sourceforge at https://sourceforge.net/projects/cpp-resolver/. I have not yet taken the time to get it into proper format for a Sandbox project, but will do that next if there seems to be enough interest in the project. I wrote up the philosophy behind the design here: http://adam.younglogic.com/?p=146 The code is currently g++ only, although I've attempted to use only core language constructs. It has no dependencies on other libraries other than stl collections. Any constructive feed back will be most appreciated. Adam

Adam Young wrote:
Having had a career that has bounced me between a few languages, I have had the opportunity to work with a couple of tools in the Java world that didn't see, to have analogues in C++. One of these is the inversion of control containers, of which Spring is one of the best known. Ken Fowler suggested the term "Dependency Injection" as a way to better describe how inversion of control is performed, and I prefer his term.
I've written a fairly simple dependency injection framework in C++ that seems to make proper use of the C++ Language. It is not attempting to do any COM like component model. Rather, it allows the developer the ability to cleanly separate the Object usage from the construction policy.
I've posted the code on Sourceforge at https://sourceforge.net/projects/cpp-resolver/. I have not yet taken the time to get it into proper format for a Sandbox project, but will do that next if there seems to be enough interest in the project. I wrote up the philosophy behind the design here:
http://adam.younglogic.com/?p=146
The code is currently g++ only, although I've attempted to use only core language constructs. It has no dependencies on other libraries other than stl collections.
Any constructive feed back will be most appreciated.
I've been using "manual" DI (mostly constructor-based injection) for a long time in C++, and would be interested in a generic DI framework. If it could be made to work with dynamically loaded classes it would be even better - perhaps with a little help from the proposed Boost.Plugin library that was under development some time ago. That being said, you'll need to provide some more documentation in order for at least me to have any specific comments. Starting out with some more snippets and examples would be a great idea, IMHO. Some desired functionality off the top of my head: - Simple registration, preferably in some declarative (instead of imperative) way. - Allow e.g. manual, thread-specific, stack-based (see below as well) and global registration. Consumers should not need to be aware of which one they are using. - It should be possible to specify fallback/priority policies; e.g. stack-based -> thread-specific -> global. - Support for temporarily overriding resolvers; e.g. scoped_resolver<T, ...>. Allows for easier test case development, among other things. - Support for injecting specific instances as well as types/factories. Regards, Johan Nilsson

On Tue, 2009-10-27 at 08:52 +0100, Johan Nilsson wrote:
Adam Young wrote:
Having had a career that has bounced me between a few languages, I have had the opportunity to work with a couple of tools in the Java world that didn't see, to have analogues in C++. One of these is the inversion of control containers, of which Spring is one of the best known. Ken Fowler suggested the term "Dependency Injection" as a way to better describe how inversion of control is performed, and I prefer his term.
I've written a fairly simple dependency injection framework in C++ that seems to make proper use of the C++ Language. It is not attempting to do any COM like component model. Rather, it allows the developer the ability to cleanly separate the Object usage from the construction policy.
I've posted the code on Sourceforge at https://sourceforge.net/projects/cpp-resolver/. I have not yet taken the time to get it into proper format for a Sandbox project, but will do that next if there seems to be enough interest in the project. I wrote up the philosophy behind the design here:
http://adam.younglogic.com/?p=146
The code is currently g++ only, although I've attempted to use only core language constructs. It has no dependencies on other libraries other than stl collections.
Any constructive feed back will be most appreciated.
I've been using "manual" DI (mostly constructor-based injection) for a long time in C++, and would be interested in a generic DI framework. If it could be made to work with dynamically loaded classes it would be even better - perhaps with a little help from the proposed Boost.Plugin library that was under development some time ago.
That being said, you'll need to provide some more documentation in order for at least me to have any specific comments. Starting out with some more snippets and examples would be a great idea, IMHO.
The code is currently structed as a header only. https://cpp-resolver.svn.sourceforge.net/svnroot/cpp-resolver/TRUNK/include/... The sourceforge svn repo has the sample code checked in here: https://cpp-resolver.svn.sourceforge.net/svnroot/cpp-resolver/TRUNK/examples... Sorry that I didn't make the clearer.
Some desired functionality off the top of my head:
- Simple registration, preferably in some declarative (instead of imperative) way.
This is my goal. The idea is the registration happens prior to calling main. I've used some macros to simplify: For example: #define REGISTER(CLASS) \ bool register##CLASS(){ \ supply<CLASS>::configure(); \ return true; \ } \ static bool __registered##CLASS = register##CLASS() This version registers a class with a default factory...bascially a noargs constructor, and is cleaned up by a destructor call. I'm adding more macros like these as I need them. They are listed at the bottom of the header file.
- Allow e.g. manual, thread-specific, stack-based (see below as well) and global registration. Consumers should not need to be aware of which one they are using.
Yes, this is supported. Part of my approach was to try and allow the application developer the flexibility to define their own hierarchy. Thus, only the global scope is explicitly defined, but you can define other scopes that make sense to your application, and means of navigation from one to another. Component resolution is done from smallest to larges scope, so if you just have thread local and global, the fetch would attempt to resolve thread local first, and then global. See this code, which is the heart of the process. static T* fetch(Zone& zone){ Zone* zonep = &zone; T * val = object_map[zonep]; if (!val){ activator<T> act = activator_map[zone.zoneType]; if (0 == act.factory_) { if (zone.parent_){ return fetch(*zone.parent_); }else{ std::string message ("No factory function registered and no parent for "); message.push_back( Which ); throw std::logic_error(message); } } //This needs a lock in order to be thread safe. { val = (*act.factory_)(zone); object_map[&zone] = val; destroyer* d = new TDestroyer(&zone); zone.push_destroyer(d); } } return val; }
- It should be possible to specify fallback/priority policies; e.g. stack-based -> thread-specific -> global. - Support for temporarily overriding resolvers; e.g. scoped_resolver<T, ...>. Allows for easier test case development, among other things. - Support for injecting specific instances as well as types/factories.
Interesting. I hadn't thought of that. That would only resolve in a specific scope?
Regards, Johan Nilsson
_______________________________________________ Unsubscribe & other changes: http://lists.boost.org/mailman/listinfo.cgi/boost
participants (2)
-
Adam Young
-
Johan Nilsson