2011-07-08 15 views
6

Tôi có trường hợp sử dụng này rất giống với ví dụ về chân robot của Guice, ngoại trừ tôi không biết có bao nhiêu "chân". Do đó, tôi không thể sử dụng chú thích cần thiết cho ví dụ về chân robot.Tổng quát ví dụ về chân robot của guice với Multibinding

Tôi hy vọng sẽ thu thập tất cả các "chân" này trong java.util.Set với tiện ích mở rộng Multibindings của Guice.

Về mặt kỹ thuật, trong PrivateModule, tôi muốn hiển thị trực tiếp triển khai dưới dạng phần tử của tập hợp sẽ được cung cấp bởi tiện ích Multibindings. Tôi chỉ không biết làm thế nào để làm điều đó.

Để tham khảo và mã ví dụ, xem robot chân ví dụ ở đây: http://code.google.com/p/google-guice/wiki/FrequentlyAskedQuestions#How_do_I_build_two_similar_but_slightly_different_trees_of_objec


Đây là trường hợp sử dụng chính xác của tôi:

Tôi đã điều sau đây:

// Main application 
public interface MyTree {...} 
public interface MyInterface { 
    public MyTree getMyTree() {} 
} 
public abstract class MyModule extends PrivateModule {} 
public class MyManager { 
    @Inject MyManager (Set<MyInterface> interfaces){ this.interfaces = interfaces } 
} 
public class MainModule extends AbstractModule { 
    public void configure() { 
    // Install all MyModules using java.util.ServiceLoader. 
    } 
} 


// In expansion "square.jar" 
public class SquareTree implements MyTree {...} 
public class SquareImplementation implements MyInterface { 
    @Inject SquareImplementation (MyTree tree) { this.tree = tree; } 
    public MyTree getMyTree() { return this.tree; } 
} 
public class SquareModule extends MyModule { // correctly defined as a ServiceLoader's service. 
    public void configure() { 
    // How to make this public IN a multibinder's set? 
    bind(MyInterface.class).to(SquareImplementation.class); 

    // Implementation specific to the Squareimplementation. 
    bind(MyTree.class).to(SquareTree.class); 
    } 
} 

// In expansion "circle.jar" 
public class CircleTree implements MyTree {...} 
public class CircleImplementation implements MyInterface { 
    @Inject CircleImplementation (MyTree tree) { this.tree = tree; } 
    public MyTree getMyTree() { return this.tree; } 
} 
public class CircleModule extends MyModule { // correctly defined as a ServiceLoader's service. 
    public void configure() { 
    // How to make this public IN a multibinder's set? 
    bind(MyInterface.class).to(CircleImplementation.class); 

    // Implementation specific to the Circle implementation. 
    bind(MyTree.class).to(CircleTree.class); 
    } 
} 

Kể từ Tôi đang nói về các lọ mở rộng, tôi không biết chúng lúc đầu, tôi thậm chí không biết có bao nhiêu trong số chúng tồn tại: Tôi cần phải tải MyModule s với j.u.ServiceLoader và mỗi mô-đun nên xác định việc thực hiện MyInterface (hai phần này là ok).

Vấn đề là nhận tất cả triển khai MyInterface trong một bộ (trong MyManager). Làm thế nào tôi có thể làm điều đó?


Giải pháp, hoàn toàn dựa trên Jesse của câu trả lời:

// Create the set binder. 
Multibinder<MyInterface> interfaceBinder = Multibinder.newSetBinder(binder(), MyInterface.class, MyBinding.class); 

// Load each module that is defined as a service. 
for (final MyModule module : ServiceLoader.load(MyModule.class)) { 

    // Generate a key with a unique random name, so it doesn't interfere with other bindings. 
    final Key<MyInterface> myKey = Key.get(MyInterface.class, Names.named(UUID.randomUUID().toString())); 
    install(new PrivateModule() { 
    @Override protected void configure() { 
     // Install the module as part of a PrivateModule so they have full hands on their own implementation. 
     install(module); 
     // Bind the unique named key to the binding of MyInterface. 
     bind(myKey).to(MyInterface.class); 
     // Expose the unique named binding 
     expose(myKey); 
    } 
    }); 
    // bind the unique named binding to the set 
    interfaceBinder.addBinding().to(myKey); 
} 

này cho phép tôi không buộc các "khách hàng" để mở rộng một PrivateModule, nhưng thay vì sử dụng bất kỳ thực hiện mô-đun nếu MyModule là một giao diện mở rộng Mô-đun.

Trả lời

9

Có vẻ như bạn sẽ cần phải nhảy qua một số vòng để thúc đẩy các ràng buộc từ mô-đun riêng để chúng có thể nằm trong nhánh đa cấp của đầu phun.

này nên làm việc:

public class SquareModule extends AbstractModule { // does not extend PrivateModule 
    @Overide public void configure() { 
    // this key is unique; each module needs its own! 
    final Key<MyInterface> keyToExpose 
     = Key.get(MyInterface.class, Names.named("square")); 

    install(new PrivateModule() { 
     @Override public void configure() { 

     // Your private bindings go here, including the binding for MyInterface. 
     // You can install other modules here as well! 
     ... 

     // expose the MyInterface binding with the unique key 
     bind(keyToExpose).to(MyInterface.class); 
     expose(keyToExpose); 
     } 
    }); 

    // add the exposed unique key to the multibinding 
    Multibinder.newSetBinder(binder(), MyInterface.class).addBinding().to(keyToExpose); 
    } 
} 

workaround này là cần thiết vì multibindings cần phải xảy ra tại injector cấp cao nhất. Nhưng các ràng buộc mô-đun riêng không hiển thị với bộ phun đó, vì vậy bạn cần phơi bày chúng.

+0

Cảm ơn Jesse, tuy nhiên sau khi đọc câu trả lời của bạn, tôi không chắc tôi đã giải thích đúng vấn đề. Vì vậy, tôi đã sửa câu hỏi của mình bằng một ví dụ. Bây giờ điều này có dễ hiểu hơn không? –

+0

Ok, tôi sẽ kiểm tra câu trả lời mới của bạn và báo cáo kết quả ở đây. –

+0

Vâng, nó hoạt động hoàn hảo. Nó khá khó để làm cho nó có thể mô-đun hóa được, nhưng không sao cả. –