Dagger - 是否可以根据继承选择提供者?

时间:2014-07-27 09:32:40

标签: dependency-injection dagger

目前我有一个Base类,其中包含我想要注入的成员。但是,我希望此成员的具体类型依赖于实例化的Subclass。我的目标是沿着这些方向:

public interface StringInterface {
    public String getString();
}

public class HelloStringConcrete implements StringInterface {
    public String getString() {
        return "Hello";
    }
}

public class WorldStringConcrete implements StringInterface {
    public String getString() {
        return "World";
    }
}

public abstract class Base {
    @Inject StringInterface member;

    public Base() { 
        // Assume access to object graph
        MyObjectGraph.get().inject(this);
    }

    public void printSomething() {
        System.out.println(member.getString());
    }
}

public class SubclassHello extends Base {}
public class SubclassWorld extends Base {}

@Module(injects = {SubclassHello.class})
public class HelloModule {
    @Provides StringInterface provideStringInterface() {
        return new HelloStringConcrete();
    }
}

@Module(injects = {SubclassWorld.class})
public class WorldModule {
    @Provides StringInterface provideStringInterface() {
        return new WorldStringConcrete();
    }
}

所以现在我想做的是:

@Module(
    includes = {
        HelloModule.class,
        WorldModule.class
    }
)
public class BigModule {}

// Somewhere in another piece of code...
objectGraph = ObjectGraph.create(new BigModule());

// In yet another piece of code...

SubclassHello hello = new SubclassHello();
SubclassWorld world = new SubclassWorld();

hello.printSomething();
world.printSomething();
// Hopefully would result in :
// Hello
// World

但是这种类型的设置不起作用,因为包含两个具有相同提供程序的模块将在编译时导致重复的提供程序错误。在没有引入@Named@Qualifer注释或通过graph.plus()使用范围图扩展来查看此问题的解决方案会很酷,因为这些策略必然会引入与子类的耦合

1 个答案:

答案 0 :(得分:0)

这是可能的,但我认为下面附带的代码比使用范围图或注释更加耦合。基本上你可以使用构造函数注入来为你的注入注入具体的依赖 SubclassHelloSubclassWorld

public abstract class Base {

    private final StringInterface member;

    public Base(StringInterface member) {
        this.member = member;
    }
    ...
}

@Module(injects = {SubclassWorld.class})
public class WorldModule {

    @Provides
    WorldStringConcrete provideStringInterface() {
        return new WorldStringConcrete();
    }
}

public class SubclassWorld extends Base {

    @Inject
    public SubclassWorld(WorldStringConcrete worldStringConcrete) {
        super(worldStringConcrete);
    }
}


@Module(injects = {SubclassHello.class})
public class HelloModule {

    @Provides
    HelloStringConcrete provideStringInterface() {
        return new HelloStringConcrete();
    }
}

public class SubclassHello extends Base {

    @Inject
    public SubclassHello(HelloStringConcrete helloStringConcrete) {
        super(helloStringConcrete);
    }
}

// Somewhere in another piece of code...
ObjectGraph objectGraph = ObjectGraph.create(new BigModule());

// In yet another piece of code...
SubclassHello hello = objectGraph.get(SubclassHello.class);
SubclassWorld world = objectGraph.get(SubclassWorld.class);

我认为还有其他解决方案。 Dagger怎么能找出应该向具体类注入哪些StringInterface实现?