2012-01-28 11 views
8

È possibile utilizzare la variazione del tipo negli eventi CDI? qui è il caso:Come utilizzare l'ereditarietà e gli elenchi di eventi CDI?

  • Supponiamo che io sono un tipo di evento radice MyEvent e sottoclasse DummyEvent
  • Il mio obiettivo è quello di elaborare un elenco di eventi ha ricevuto da una fonte remota List<? extends MyEvent>, contenente DummyEvent casi

Come posso fare questo?

Se eseguo il loop della raccolta chiamando fire() per ciascun evento, invocherà i metodi @Observes MyEvent evt ma non @Observes DummyEvent evt.

** Aggiornamento **

Creato un codice di esempio per chiarire la questione:

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

vorrei che la manifestazione di essere licenziato due volte, una volta singolarmente e una volta dalla lista .

+0

Quale implementazione CDI stai utilizzando? –

+0

Saldare in jboss come 7 –

risposta

1

Mhh Non capisco ... come si presenta il tuo codice reale prima dell'inizio dell'evento? ASFAIK si inietta l'interfaccia javax.enterprise.event.Event e si passa un'istanza al suo metodo fire, che dichiara l'osservatore chiamato. E se l'ereditarietà è coinvolta, come nel tuo caso, entrambi gli osservatori verrebbero chiamati, se fai un DummyEvent. Se si desidera specificare ulteriormente gli eventi, si utilizzeranno i qualificatori.

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

/* Edit */

Il "problema" è la seguente riga di codice:

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

Non appena si specifiy il tipo di evento (MyEvent.class), il tipo di istanza dell'evento effettivo (evt) non ha più importanza. Una possibilità è di estendere la tua classe hirachy con i qualificatori. Ad esempio:

@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"); 
    }  
} 

Dopo che specificano ulteriormente l'Observer:

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

Infine, quando hai appena accedere alle classi di base, come nel tuo esempio in cui si itarate attraverso un elenco, è possibile specificare l'esatto digitare/qualificatore prima di sparare l'evento come quello:

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

come accennato in precedenza, se si dispone di un osservatore generale (vedi sotto), verrà chiamato per ogni evento.

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

Vedere l'esempio di codice che ho appena aggiunto, sperare di rendere il problema un po 'più chiaro. –

+0

Modificata la risposta, forse aiuta. –

+0

Aiuta, ma c'è una soluzione che utilizza solo i tipi ... grazie per la pubblicazione, ho imparato il trucco :) –

Problemi correlati