Search code examples
eclipsedependency-injectionguicee4

Add Eclipse 4 RCP context function programmatically


I am trying to bridge Guice 4 injector with Eclipse 4 RCP DI mechanism. What I would like to do is to create a ContextFunction, which would look up for values in Guice injector and bind them in IEclipseContext, something like this:

import org.eclipse.e4.core.contexts.ContextFunction;
import org.eclipse.e4.core.contexts.IEclipseContext;

import com.google.inject.Injector;

public class GuiceRCPBridgeFunction  extends ContextFunction 
{
    private Injector injector;

    public GuiceRCPBridgeFunction(Injector injector)
    {
        this.injector = injector;
    }

    @Override
    public Object compute(IEclipseContext context, String contextKey) 
    {
        // convert string key to type:
        Class<?> guiceKey = null;
        try {
            guiceKey = injector.getClass().getClassLoader().loadClass(contextKey);
        } 
        catch (ClassNotFoundException e) { throw new RuntimeException( e ); }

        // get instance from the injector:
        Object instance = injector.getInstance( guiceKey );

        // cache the instance in the eclipse context:
        context.set( contextKey, instance );

        return instance;
    }
}

I would like to know if there a way to attach this function after the Injecter is created, so that I could avoid putting the Injecter itself into the IEclipseContext?


Solution

  • Following seems to work, after putting the function under specific keys, as suggested by greg-449:

    import org.eclipse.e4.core.contexts.ContextFunction;
    import org.eclipse.e4.core.contexts.IEclipseContext;
    
    import com.google.inject.Injector;
    import com.google.inject.Key;
    
    /**
     * Links guice and e4 RI  
     */
    public class GuiceRCPBridgeFunction  extends ContextFunction 
    {
    
        public static void link( Injector injector, IEclipseContext context )
        {
            GuiceRCPBridgeFunction function = new GuiceRCPBridgeFunction(injector);
            // add this function for every injector binding:
            for(Key <?> key : injector.getBindings().keySet())
            {
                String contextKey = key.getTypeLiteral().toString(); 
                Class classKey = function.loadClass( contextKey );
                context.set( classKey, function );
            }
        }
    
        private Injector injector;
    
        public GuiceRCPBridgeFunction(Injector injector)
        {
            this.injector = injector;
    
        }
    
        @Override
        public Object compute(IEclipseContext context, String contextKey) 
        {
            // convert string key to type:
            Class classKey = loadClass( contextKey );
            // get instance from the injector:
            Object instance = injector.getInstance( classKey );
            // cache the instance in the eclipse context:
            context.set(classKey, instance);
    
            return instance;
        }
    
        protected Class <?> loadClass( String className )
        {
            Class<?> guiceKey = null;
            try {
                guiceKey = injector.getClass().getClassLoader().loadClass(className);
            } 
            catch (ClassNotFoundException e) { throw new IllegalArgumentException( e ); }
    
            return guiceKey;
        }
    }