Created
June 20, 2013 19:57
-
-
Save amoerie/5826079 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public class SmartBox { | |
private Map<Class, Class> bindings; | |
public SmartBox() { | |
this.bindings = new HashMap<>(); | |
} | |
/** | |
* Binds {@TService} class to {@TInstance} | |
* | |
* @param service | |
* the service class to bind to | |
* @param instance | |
* the instance that will be bound to the service | |
* @param <TService> | |
* the type of the service | |
* @param <TInstance> | |
* the type of the instance that must extend (or implement) {@TService} | |
*/ | |
public <TService, TInstance extends TService> void bind(Class<TService> service, Class<TInstance> instance) { | |
bindings.put(service, instance); | |
} | |
/** | |
* Gets an instance of {@TService} | |
* | |
* @param service | |
* the class of the requested service | |
* @param <TService> | |
* the requested service | |
* @return an instance of {@TService} | |
*/ | |
public <TService> TService get(Class<TService> service) | |
throws IllegalAccessException, InstantiationException, InvocationTargetException { | |
if (bindings.containsKey(service)) | |
// this service is bound! Let's get the bound instance for it. | |
return (TService) get(bindings.get(service)); | |
else | |
// no registered binding, let's see if we can resolve it | |
return resolve(service); | |
} | |
private <TService> TService resolve(Class<TService> service) | |
throws IllegalAccessException, InvocationTargetException, InstantiationException { | |
// get constructor | |
Constructor<?>[] constructors = service.getConstructors(); | |
if (constructors.length == 0) | |
throw new IllegalArgumentException("No public constructor found for " + service); | |
if (constructors.length > 1) | |
throw new IllegalArgumentException("More than one public constructor found in " + service); | |
Constructor constructor = constructors[0]; | |
// inspect the constructor parameters | |
Class[] requestedServices = constructor.getParameterTypes(); | |
// resolve each constructor parameter | |
Object[] resolvedServices = new Object[requestedServices.length]; | |
for (int i = 0; i < requestedServices.length; i++) { | |
resolvedServices[i] = get(requestedServices[i]); | |
} | |
// invoke constructor | |
return (TService) constructor.newInstance(resolvedServices); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment