Some background
I am developing a small DI Container based on Lambda expressions. I have the interface representing the lambda:
@FunctionalInterface
public interface LambdaOp<T> {
T resolve();
}
And this is the (very simplified) Container:
public class Container {
private final Map<Class<?>, LambdaOp<?>> bindings;
public <T> void bind(Class<T> clazz, LambdaOp<? extends T> lambda) {
bindingd.put(clazz, lambda);
}
public <T> T resolve (Class<T> clazz) {
LambdaOp<?> lambda = bindings.get(clazz);
return (T) lambda.resolve();
}
}
With this implementation I can do something like that:
container.bind(
FooInterface.class,
() -> {
FooImplementation foo = new FooImplementation();
foo.setParameterA(paramA);
//do whatever needed to configure it
return foo;
}
);
FooInterface foo2 = container.resolve(FooInterface.class);
It is working ok and it is nice because the compiler won't let me do something like this:
container.bind(
FooInterface.class,
() -> new BarImplementation() //compiler error; Bar does not implement Foo
);
The problem
The bindings Map itself does not guarantee that LambdaOp will have a generic type which extends the Class used as key.
private final Map<Class<?>, LambdaOp<?>> bindings;
As a result I receive an unchecked warning at the line:
return (T) lambda.resolve();
I suppose that the bind method signature is enough to guarantee the cohesion (is it?) but still feel some bad smell.
Is there any way to implement it on a more cohesive way?
EDIT:
The complete code is at github. I have made a lot of changes recently and README.md is very a little bit outdated.