2009-03-20 35 views
15

Quiero tener una biblioteca que tendrá una función que acepte un objeto para su parámetro.Devolución de llamada en C#

Con este objeto quiero poder llamar a una función especificada cuando X termina. La función que se llamará debe ser especificada por la persona que llama, y ​​X será realizada y supervisada por la biblioteca.

¿Cómo puedo hacer esto?

Como referencia que estoy usando C# y .NET 3.5

+0

Sospecho que su respuesta contiene degates, eventos o ambos. Sin embargo, después de leer tu pregunta un par de veces, no puedo entender lo que estás preguntando. – Brian

+1

Aquí hay una muestra http://blog.jerrynixon.com/2011/11/there-are-lots-of-things-that-take-long.html –

Respuesta

38

de Suministro un delegado y utilizar un delegado anónima o expresión lambda

public static void DoWork(Action processAction) 
{ 
    // do work 
    if (processAction != null) 
    processAction(); 
} 

public static void Main() 
{ 
    // using anonymous delegate 
    DoWork(delegate() { Console.WriteLine("Completed"); }); 

    // using Lambda 
    DoWork(() => Console.WriteLine("Completed")); 
} 

O utilizar una interfaz

public interface IObjectWithX 
{ 
    void X(); 
} 

public class MyObjectWithX : IObjectWithX 
{ 
    public void X() 
    { 
    // do something 
    } 
} 

public class ActionClass 
{ 
    public static void DoWork(IObjectWithX handlerObject) 
    { 
    // do work 
    handlerObject.X(); 
    } 
} 

public static void Main() 
{ 
    var obj = new MyObjectWithX() 
    ActionClass.DoWork(obj); 
} 
1

El objeto en cuestión tendrá que implementar una interfaz proporcionada por usted. Tome la interfaz como parámetro, y luego puede llamar a cualquier método que exponga la interfaz. De lo contrario, no tienes manera de saber de qué es capaz el objeto. Eso, o podrías tomar un delegado como parámetro y llamar eso.

+0

Esto es exactamente correcto. – plinth

6

Suena como una receta perfecta para los delegados, en particular, las devoluciones de llamada con delegados son exactamente cómo se maneja esto en el patrón asincrónico en .NET.

La persona que llama normalmente le pasará un estado y un delegado, y los almacena en el contexto que tenga, luego llama al delegado pasándole el estado y cualquier resultado que pueda tener.

Puede hacer el estado simplemente object o utilizar un delegado genérico y tomar el estado del tipo apropiado, p. Ej.

public delegate void Callback<T>(T state, OperationResult result) 

continuación:

public void DoSomeOperation(int otherParameterForWhateverReason, 
          Callback<T> callback, T state) 

Como usted está utilizando .NET 3.5 es posible que desee utilizar los Func<...> y Action<...> tipos de delegado existentes, pero se puede encontrar que hace que sea más claro para declarar tu propio. (El nombre puede aclarar para qué lo está usando).

+2

Sugiero que leas sobre delegados entonces (y genéricos, potencialmente). Mi artículo sobre delegados y evvents está en http://pobox.com/~skeet/csharp/events.html –

1

¿Existe alguna razón para que su biblioteca no proporcione un evento público para ser despedido cuando la operación se complete? Entonces la persona que llama podría simplemente registrarse para manejar el evento y no tiene que preocuparse por pasar objetos o delegados.

El objeto que implementa una interfaz que ha proporcionado funcionaría, pero parece ser más el enfoque de Java que el enfoque .NET. Los eventos me parecen un poco más limpios.

+0

No sé cómo hacer eventos ... – Malfist

+0

Consulte http://pobox.com/~skeet/csharp/events.html para obtener más información acerca de los eventos. Pueden o no ser apropiados para su situación, pero vale la pena conocerlos. –

-2

Puede utilizar System.Action disponible en C# .NET para las funciones de devolución de llamada. Compruebe este ejemplo de ejemplo:

//Say you are calling some FUNC1 that has the tight while loop and you need to 
    //get updates on what percentage the updates have been done. 
    private void ExecuteUpdates() 
    { 
     Func1(Info => { lblUpdInfo.Text = Info; }); 
    } 

    //Now Func1 would keep calling back the Action specified in the argument 
    //This System.Action can be returned for any type by passing the Type as the template. 
    //This example is returning string. 
    private void Func1(System.Action<string> UpdateInfo) 
    { 
     int nCount = 0; 
     while (nCount < 100) 
     { 
      nCount++; 
      if (UpdateInfo != null) UpdateInfo("Counter: " + nCount.ToString()); 
      //System.Threading.Thread.Sleep(1000); 
     } 
    } 
+0

Esa no es una alternativa a una devolución de llamada; que ** es ** una devolución de llamada. – Servy

Cuestiones relacionadas