2012-01-28 10 views
8

Czy można stosować wariancję typu w zdarzeniach CDI? oto przypadek:Jak korzystać z dziedziczenia i list wydarzeń CDI?

  • Załóżmy, że mam typ zdarzenia korzeń MyEvent i podklasa DummyEvent
  • Moim celem jest przetwarzanie lista zdarzeń odbieranych ze zdalnego źródła List<? extends MyEvent> zawierający DummyEvent instancje

Jak mogę to zrobić?

Jeśli przechodzę przez kolekcję wywołując fire() dla każdego zdarzenia, wywoła ona metody @Observes MyEvent evt, ale nie @Observes DummyEvent evt.

** Aktualizacja **

Utworzono przykładowy kod w celu wyjaśnienia problemu:

https://github.com/jfaerman/jfaerman/blob/master/test-cdi/src/main/java/jfaerman/App.java

chciałbym zdarzenie zostać zwolniony dwa razy, raz indywidualnie i raz z listy .

+0

Którą implementację CDI używasz? –

+0

spoina w jboss jako 7 –

Odpowiedz

1

Mhh Nie rozumiem ... jak wygląda twój aktualny kod przed wydarzeniem? ASFAIK wstrzykujesz interfejs javax.enterprise.event.Event i przekazujesz instancję do metody fire, która przez to deklaruje wywoływanego obserwatora. A jeśli w grę wchodzi dziedziczenie, tak jak w twoim przypadku, Observer zostanie wezwany, jeśli wystrzelisz DummyEvent. Jeśli chcesz dokładniej określić zdarzenia, w których będziesz używał kwalifikatorów.

@Inject @Any Event<DummyEvent> dummyEvent; 
... 
dummyEvent.fire(list.get(i)); 

/* edit */

"Problem" jest następujący wiersz kodu:

weld.event().select(MyEvent.class).fire(evt); 

Jak najszybciej specifiy typ tej imprezy (MyEvent.class) rzeczywisty typ zdarzenia (evt) nie ma już znaczenia. Jedną z możliwości jest rozszerzenie klasy hirachy o kwalifikatory. Np:

@ChildEvent.Child 
public class ChildEvent extends BaseEvent{ 

    @Qualifier 
    @Retention(RetentionPolicy.RUNTIME) 
    @Target({ElementType.TYPE, ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) 
    public @interface Child{ 
    } 

    public void eventAction() { 
     System.out.println("child"); 
    }  
} 

Potem dodatkowo określić Observer:

public void observerChild(@Observes @ChildEvent.Child BaseEvent child){ 
     System.out.println("child with annotation event"); 
} 

Wreszcie, gdy masz tylko dostęp do klas bazowych, tak jak w przykładzie, gdzie itarate poprzez listy, można określić dokładną typ/kwalifikator przed wypalaniem zdarzenie tak:

for (BaseEvent e : list){ 
    childEvent.select(e.getClass().getAnnotations()[0]).fire(e); 
} 

jak wspomniano wyżej, jeśli masz ogólne Observer (pokazany poniżej), to zostanie wywołana dla każdego przypadku.

public void observerBase(@Observes BaseEvent base){ 
    System.out.println("base event"); 
} 
+0

Proszę zobaczyć przykład kodu, który właśnie dodałem, mam nadzieję, że sprawa stanie się bardziej oczywista. –

+0

Edytowałeś odpowiedź, może to pomaga. –

+0

To pomaga, ale jest rozwiązanie, które wykorzystuje tylko typy ... dzięki za publikację, nauczyłeś się sztuczki :) –

Powiązane problemy