Hi Knut,

As I said earlier on this list, I already thought about this kind of stuff
(and implemented some "ObjectBuilder" to fulfill my needs). For me the
following points are important to keep in mind:

- possibility to create an object based on a configuration (or part of a
configuration): all the DependencySpecification objects would thus directly
created from the configuration (in this case, the dependency specifications
could be determined according to a unique name in the config, that name
would be passed to the create method).

- possibility to add additional arguments in addition to dependencies of
services or configurations (I suppose the DependencyInjector service as you
describe it would allow for that, but if we add methods that are based on
some configuration, then it must be possible to pass additional -runtime-
arguments to these methods (this is only necessary for ctor-arguments
actually, since the caller of the DependencyInjector could directly call
setters of the created objects for such additional args)

- possibility to inject the event wiring as well (it is not clear to me if
your current proposal allows for this)

Additionally (but this can be provided as another service that would use
DependencyInjector), it could be interesting to cache created objects (not
necessary all, this could be an additional setting in the config).

As I already posted it earlier, my idea about the configuration would look
like this:

<object name="OpenBoardCommand" cached="true"
        class="net.sourceforge.hiveboard.ui.command.DelegateCommand">
        <inject object="service:OpenBoardExecutor"/>
        <inject name="myService" object="service:MyService"/>
        <listener event="command"
                object="instance:ActiveViewCommandListener"/>
        <inject-arg/> 
</object>

In the example above (this is how my ObjectBuilder works), the create()
method is called as follows:

        objectBuilder.create("OpenBoardCommand", "runtime argument");

In this case, the creation is as follows:
- instantiation of the DelegateCommand class
- in the constructor, the service "OpenBoardExecutor" is passed (1st arg)
- in the constructor, the additional arg (String "runtime argument") is
passed (2nd arg)
- then the service "MyService" is setter-injected to the property
"myService"
- finally, addCommandListener() is called with a new instance of
ActiveViewCommandListener class

Don't pay attention to the names, I took this example from my current
development and added one dummy <inject> tag for setter-injection (because I
never use setter-injection in my project).

Cheers

        Jean-Francois

-----Original Message-----
From: Knut Wannheden [mailto:[EMAIL PROTECTED] 
Sent: Friday, February 25, 2005 10:18 PM
To: HiveMind Dev List
Subject: reusable dependency injection

Hi,

There have been a few discussions in the recent past about factoring
out the dependency injection logic used by the BuilderFactory and make
it available for reuse. The dependency injection logic should be
reusable by other service and interceptor factories and possibly also
other user code.

I have been playing with this a little bit and would like to discuss
my results with you. Quite possibly I'm not the only one who has been
playing with this and most certainly a few of you have good ideas on
how this should be implemented. So please take a look at what I've
done and let's see if anything comes out of it.

First I'd like to more precisely define what the very core of the
dependency injection logic should do and shouldn't do. IMO the DI
logic should be able to both perform constructor based dependency
injection (CBDI) and setter based dependency injection (SBDI) given a
specification on the dependencies. This means that autowiring would
have to be worked out at a higher level by "compiling" the dependency
specification.

At the DI logic level I've come up with something like this (details left
out):

class DependencyInjector
{
  // returns an instance of clazz configured as specified in spec
(CBDI and SBDI)
  public Object createInstance(Class clazz, DependencySpecification spec)
{...}

  // injects dependencies into object as specified by spec (only SBDI)
  public void injectDependencies(Object object,
DependencySpecification spec) {...}
}

abstract class DependencySpecification
{
  // determines whether the given constructor satisfies this
specification (for CBDI use)
  public abstract boolean isSatisfiedBy(Constructor c);

  // returns a new compound specification
  public DependencySpecification and(DependencySpecification other) {...}

  // determines whether the given other specification conflicts with
this specification
  public abstract boolean conflictsWith(DependencySpecification other);
}

class ConstructorSpecification extends DependencySpecification
{
  public static final ConstructorSpecification DEFAULT_CONSTRUCTOR_SPEC =
...;

  public ConstructorSpecification(Class type, Object value) {...}
  public ConstructorSpecification(Class type, Object value, int position)
{...}
}

class SetterSpecification extends DependencySpecification
{
  public SetterSpecification(Class type, Object value) {...}
  public SetterSpecification(Class type, Object value, String
propertyName) {...}
}

So the equivalent of:

Foo bar = new Foo(42, "foo");
bar.setName("bar");

is for example:

DependencySpecification spec = new ConstructorSpecification(String.class,
"foo")
  .and(new ConstructorSpecification(Integer.TYPE, new Integer(42)))
  .and(new SetterSpecification(String.class, "bar", "name"));

Foo bar = (Foo) new DependencyInjector().createInstance(Foo.class, spec);

(At what lengths one goes to create a simple object... :-)

Thoughts?

--knut

---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]




---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to