2009-07-30 10 views
29

Estoy haciendo una pequeña aplicación multiproceso que utiliza conectores TCP asíncronos, pero voy a ir al grano: estoy usando un evento personalizado para leer un valor de un formulario y el delegado utilizado por el evento devuelve una cadena cuando esté terminado.Devuelve un valor de un evento: ¿hay una buena práctica para esto?

Mi pregunta aquí es: ¿es correcto? ¿Está bien devolver valores de los eventos? o hay una mejor manera de hacer esto? (como usar un simple delegado en el formulario para leer los valores)

Respuesta

31

A menudo es difícil devolver los valores de los eventos. En la práctica, me resulta mucho más fácil incluir una propiedad de escritura en un conjunto de EventArgs personalizados que se pasan al evento y luego se verifican después de que se desencadena el evento, similar a la propiedad Cancelar del evento WinForms FormClosing.

+8

¿Podría detallar' incluir una propiedad de escritura en un conjunto de EventArgs personalizados que se pasa a la parte del evento? – Odys

+0

@Odys Haga el objeto EventArgument personalizado. Crea una propiedad donde viven los resultados. – Crisfole

15

El ejemplo más cercano que puedo pensar es el evento FormClosing en WinForms. Permite que el formulario cancele el evento estableciendo la propiedad eventArgs.Cancel en verdadero. Para que hagas algo similar, definirías tu propia clase de evento args con el valor de retorno como una propiedad en esa clase. Luego pase un objeto args de evento cada vez que levante el evento. Quien haya planteado el evento puede inspeccionar el objeto de evento args para el valor de retorno. Otros que están recibiendo el evento también pueden inspeccionar o cambiar el objeto de evento args.

Actualización: Me encontré con el evento AppDomain.AssemblyResolve, y parece ser un evento que devuelve un valor. Parece que solo necesitas declarar un tipo de delegado que devuelve un valor, y luego definir tu evento con ese tipo de delegado. Aunque no he intentado crear mi propio evento así. Una ventaja del uso de una propiedad en el argumento del evento es que todos los suscriptores del evento pueden ver lo que han devuelto los suscriptores anteriores.

+1

Nota: Se puede utilizar cualquier delegado para definir los eventos, por lo que también estaría bien para definir un evento como 'evento público Func algunEvento;' que sería exigible como 'bool r = SomeEvent ("foo", "bar"); ' –

26

No creo que sea una buena idea ... los eventos son básicamente delegados de multidifusión, por lo que puede haber múltiples controladores. ¿Qué valor de retorno tomará en ese caso?

6

No sé si esto es una buena práctica, pero lo hice de esta manera.

Func<DataRow, bool> IsDataValid; 

    // some other code .... 

    isValid = true; 
    if (IsDataValid != null) 
    { 
     foreach (Func<DataRow, bool> func in IsDataValid.GetInvocationList()) 
     { 
     isValid &= func(Row); 
     } 
    } 
-1
void method() 
{ 
    list<string> strings = new list<string>(); 

    dostuff += stuff; 
    dostuff += stuff; 

    dostuff(this, new EventHandlerArgs(){ Parameter = strings }) 

    foreach(string currString in strings) 
    { 
      //.... 
    } 
} 

void stuff(object sender, EventHandlerArgs e) 
{ 
    list<string> strings = e.Parameter as list<string>; 

    if (strings != null) 
    { 
     strings.Add(MyString) 
    } 
} 
+2

¡Bienvenido a stackoverflow! Siempre es mejor proporcionar una breve descripción de un código de muestra para mejorar la precisión de la publicación :) –

10

Sé que esto es las edades después del post, pero el pensamiento de añadir comentario con código de explicar Dustin Campbell respuesta para si alguien viene a través de este hilo. Me encontré con esta publicación al tratar de decidir cuál sería la mejor práctica, y esto es lo que significa la respuesta.

crear su propia clase controlador de eventos personalizado

public class myCustomeEventArgs:EventArgs 
{ 
    public bool DoOverride { get; set; } 
    public string Variable1 { get; private set; } 
    public string Variable2{ get; private set; } 

    public myCustomeEventArgs(string variable1 , string variable2) 
    { 
     DoOverride = false; 
     Variable1 = variable1 ; 
     Variables = variable2 ; 
    } 
} 

Así que cuando usted crea su delegado caso de utilizar sus argumentos de eventos creados de esta manera.

public delegate void myCustomeEventHandler(object sender, myCustomeEventArgs e); 

Y en la clase que plantea el evento, usted declara el evento.

public event myCustomeEventHandler myCustomeEvent; 

Así que cuando se dispara el evento en su clase de la clase que se detecta el evento puede simplemente en el cuerpo del conjunto de eventos e.DoOverride = true; como se declarará en la clase disparando el evento.

caso de incendio, por ejemplo:

if(myCustomeEvent != null) 
{ 
    var eventArgs = new myCustomeEventArgs("Some Variable", "Another Varaible"); 
    myCustomeEvent(this, eventArgs); 
    //Here you can now with the return of the event work with the event args 
    if(eventArgs.DoOverride) 
    { 
     //Do Something 
    } 
} 
+0

¿Cómo sabes cuándo el evento "regresará"? –

+4

Los eventos se ejecutan en el mismo hilo que los provoca. El código que ejecuta 'myCustomeEvent (...)' pasará el control (se ejecutará en el mismo subproceso) a todos los controladores de eventos suscritos. Una vez que se haya ejecutado todo su código, el control volverá a la instrucción justo después de la llamada a 'myCusomeEvent (...)'. Si no hay suscriptores, o hay suscriptores que retransmiten el evento a otro hilo, entonces todas las propiedades en 'eventArgs' tendrán su valor predeterminado (falso para' bool' y 'null' para las cadenas). –

6

Nota: solo el último evento devuelve el resultado.

class Program 
{ 
static event Func<string, bool> TheEvent; 

    static void Main(string[] args) 
    { 
     TheEvent += new Func<string, bool>(Program_TheEvent); 
     TheEvent +=new Func<string,bool>(Program_TheEvent2); 
     TheEvent += new Func<string, bool>(Program_TheEvent3); 
     var r = TheEvent("s"); //r == flase (Program_TheEvent3) 
    } 

    static bool Program_TheEvent(string arg) 
    { 
     return true; 
    } 

    static bool Program_TheEvent2(string arg) 
    { 
     return true; 
    } 

    static bool Program_TheEvent3(string arg) 
    { 
     return false; 
    }   
} 
+0

Gracias. Funciona para mi a través de un servicio de WCF – harveyt

+1

¡Gracias! Me preguntaba qué controlador de eventos "ganaría". –

0

Bucle las propiedades de los EventArgs como este y saqué sus valores X e Y.

vacío privado navBarControl1_Click (remitente del objeto, EventArgs e) { int _x = 0; int _y = 0;

 Type t = e.GetType(); 
     IList<PropertyInfo> props = new List<PropertyInfo>(t.GetProperties()); 

     foreach (PropertyInfo prop in props) 
     { 
      if (prop.Name == "X") 
      { 
       object propValue = prop.GetValue(e, null); 
       _x = Convert.ToInt32(propValue); 
      } 
      if (prop.Name == "Y") 
      { 
       object propValue = prop.GetValue(e, null); 
       _y = Convert.ToInt32(propValue); 
      } 
     } 
+2

por favor aclare más su respuesta – Mostafiz

Cuestiones relacionadas