To make it clearer what I'm after, below is a test which, if it
passed, would mean the problem is solved.

The money shot is how getTheType() is implemented (it should be passed
whatever it actually needs).  I've tried implementing
ProviderInstanceBinding and friends on PropsProvider, and introspected
what I get passed in a debugger - but nowhere have I found an object
with a reference to the type being injected into (InjectionPoint looks
promising, but I'm always passed an empty collection of them).

I'm guessing that the problem here is that Guice wants to be *told*
what to inject imperatively, and I want my code to be *asked* - which
Provider solves, but without enough metainfo to answer the question.

Since I am processing the annotation at compile time, I'm fine with
generating whatever's called for;  and probably some sort horrible mix
of brute-force classpath scanning and custom scopes could be made to
do it.  But it seems like there should be a clean, elegant way to do
this.

public class ValueBindingTest {
    private static final class M extends AbstractModule {
        private final Properties propsA = new Properties();
        private final Properties propsB = new Properties();
        private final Properties defaults = new Properties();

        M() {
            propsA.setProperty("a", "a");
            propsB.setProperty("a", "b");
            defaults.setProperty("a", "nothing");
        }

        public void configure() {
            MyNamedImpl stringInjectionsOfA = new MyNamedImpl("a"); //
in real life we'd iterate all the keys
 
bind(String.class).annotatedWith(stringInjectionsOfA).toProvider(new
PropsProvider(stringInjectionsOfA.value()));
        }

        private Class<?> getTheType() {
            //What to do here?  I need the type of the object being
injected?
            return InNamespaceTwo.class;
        }

        public Properties getProperties() {
            Class<?> injectingInto = getTheType();
            MyNamespace ns =
injectingInto.getAnnotation(MyNamespace.class);
            Properties props = defaults; //fallback
            if (ns != null) {
                switch (ns.value()) {
                    case "one":
                        return propsA;
                    case "two":
                        return propsB;
                }
            }
            return props;
        }
        class PropsProvider implements Provider<String> {
            private final String key;

            public PropsProvider(String key) {
                this.key = key;
            }

            @Override
            public String get() {
                return getProperties().getProperty(key);
            }
        }
    }
    @Target(ElementType.PARAMETER)
    @BindingAnnotation
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyNamed {
        String value();
    }
    private static class MyNamedImpl implements MyNamed {
        private final String value;

        public MyNamedImpl(String value) {
            this.value = value;
        }

        @Override
        public String value() {
            return value;
        }

        @Override
        public Class<? extends Annotation> annotationType() {
            return MyNamed.class;
        }

        public boolean equals(Object o) {
            System.out.println("Equals " + o);
            return o instanceof MyNamed && value().equals(((MyNamed)
o).value());
        }

        public int hashCode() {
            return (127 * "value".hashCode()) ^ value.hashCode();
        }
    }
    @Target({ElementType.PACKAGE, ElementType.TYPE, ElementType.FIELD,
ElementType.LOCAL_VARIABLE})
    @Retention(RetentionPolicy.RUNTIME)
    @interface MyNamespace {
        String value();
    }
    @MyNamespace("one")
    static class InNamespaceOne {
        private final String value;

        @Inject
        public InNamespaceOne(@MyNamed("a") String value) {
            this.value = value;
        }
    }
    @MyNamespace("two")
    static class InNamespaceTwo {
        private final String value;

        @Inject
        public InNamespaceTwo(@MyNamed("a") String value) {
            this.value = value;
        }
    }

    static class NotNamespaced {
        private final String value;

        @Inject
        public NotNamespaced(@MyNamed("a") String value) {
            this.value = value;
        }
    }

    @Test
    public void test() {
        Injector inj = Guice.createInjector(new M());
        InNamespaceOne a = inj.getInstance(InNamespaceOne.class);
        InNamespaceTwo b = inj.getInstance(InNamespaceTwo.class);
        NotNamespaced c = inj.getInstance(NotNamespaced.class);
        assertEquals("a", a.value);
        assertEquals("b", b.value);
        assertEquals("nothing", c.value);
    }
}

-- 
You received this message because you are subscribed to the Google Groups 
"google-guice" group.
To post to this group, send email to google-guice@googlegroups.com.
To unsubscribe from this group, send email to 
google-guice+unsubscr...@googlegroups.com.
For more options, visit this group at 
http://groups.google.com/group/google-guice?hl=en.

Reply via email to