È possibile generare un evento su un oggetto, dall'esterno di quell'oggetto, senza una funzione personalizzata

StackOverflow https://stackoverflow.com/questions/1230223

  •  22-07-2019
  •  | 
  •  

Domanda

public class a
{
   public event eventhandler test;
   public void  RaiseTest(){//fire test}
}

È possibile aumentare il test su questa classe, al di fuori di questa classe, senza chiamare il metodo?

Fondamentalmente ho un gran numero di eventi che devono essere generati da una fonte esterna e non voglio creare una funzione Raise () per ognuno.

È possibile creare un Raise () generico che accetta l'evento da sollevare come parametro? quindi sarebbe ancora chiamato dall'interno della classe?

È stato utile?

Soluzione

Puoi farlo tramite Reflection, ma è meno che ovvio. Se dichiari un evento in C #, un campo verrà aggiunto alla classe con il nome dell'evento + " Event " ;. Se si chiama GetValue sul campo, verrà restituita un'istanza MulticastDelegate.

Una volta che hai il MulticastDelegate, puoi ottenere l'elenco di invocazioni e invocare ogni membro a turno:

EventArgs e = new EventArgs(myClassInstance);  // Create appropriate EventArgs

MulticastDelegate eventDelagate = 
    this.GetType().GetField(theEventName + "Event",
    System.Reflection.BindingFlags.Instance | 
    System.Reflection.BindingFlags.NonPublic).GetValue(myClassInstance) as MulticastDelegate;

Delegate[] delegates = eventDelagate.GetInvocationList();
foreach (Delegate del in delegates) {  
      del.Method.Invoke(del.Target, new object[] { myClassInstance, e }); 
}

Nota che questo richiede l'ottenimento di un campo NonPublic dall'istanza, quindi funzionerà solo in piena fiducia ed è molto limitato.

  

È possibile creare un Raise () generico che accetta l'evento da sollevare come parametro? quindi sarebbe ancora chiamato dall'interno della classe?

Sì. Sarebbe abbastanza facile modificare il codice sopra per farlo. Sostituisci semplicemente " myClassInstance " con questo. Ciò consentirà in realtà di funzionare correttamente anche in piena fiducia, poiché il BindingFlag non pubblico non sarà più un problema.

Altri suggerimenti

  

È possibile aumentare il test su questa classe, al di fuori di questa classe, senza chiamare il metodo?

Risposta breve: no.

Solo la classe che dichiara l'evento può sollevarlo

  

È possibile creare un Raise () generico che accetta l'evento da sollevare come parametro? quindi sarebbe ancora chiamato dall'interno della classe?

Non credo, almeno non facilmente ... Anche usando la riflessione, non esiste un metodo EventInfo.Invoke . AFAIK, l'unico modo per aumentare l'evento è staticamente all'interno della classe

EDIT: in realtà può essere fatto (vedi la risposta di Reed), ma con la limitazione che l'app deve funzionare in piena fiducia.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top