2009-03-20 6 views
15

Je veux avoir une bibliothèque qui aura une fonction qui accepte un objet pour son paramètre.Callbacks in C#

Avec cet objet, je veux être en mesure d'appeler une fonction spécifiée lorsque X est terminé. La fonction qui sera appelée doit être spécifiée par l'appelant, et X sera fait et surveillé par la bibliothèque.

Comment est-ce que je peux faire ceci?

Pour référence, je suis en utilisant C# et .NET 3.5

+0

Je suppose que votre réponse contient des événements, des événements ou les deux. Cependant, après avoir lu votre question plusieurs fois, je suis incapable de comprendre ce que vous me demandez. – Brian

+1

Voici un exemple http://blog.jerrynixon.com/2011/11/there-are-lots-of-things-that-take-long.html –

Répondre

38

offre un délégué et d'utiliser un délégué anonyme ou Lambda Expression

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

Ou utiliser une interface

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

L'objet en question devra mettre en œuvre une interface fournie par vous. Prenez l'interface en tant que paramètre, puis vous pouvez appeler n'importe quelle méthode exposée par l'interface. Sinon, vous n'avez aucun moyen de savoir de quoi l'objet est capable. Cela, ou vous pourriez prendre un délégué comme paramètre et l'appeler.

+0

C'est exactement correct. – plinth

6

Cela ressemble à une recette parfaite pour les délégués - en particulier, les rappels avec les délégués sont exactement comment cela est géré dans le modèle asynchrone dans .NET. L'appelant vous passerait habituellement un certain état et un délégué, et vous les stockez dans n'importe quel contexte, puis appelez le délégué en lui passant l'état et quel que soit le résultat que vous pourriez avoir.

Vous pouvez soit rendre l'état juste object ou potentiellement utiliser un délégué générique et prendre l'état du type approprié, par ex.

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

Puis:

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

Comme vous utilisez .NET 3.5, vous pouvez utiliser les Func<...> existants et Action<...> types de délégués, mais vous pouvez trouver le rend plus clair de déclarer le tien. (Le nom peut rendre plus clair ce pour quoi vous l'utilisez.)

+2

Je vous suggère de lire ensuite les délégués (et les génériques, potentiellement). Mon article sur les délégués et evvents est à http://pobox.com/~skeet/csharp/events.html –

1

Y a-t-il une raison pour que votre bibliothèque n'offre pas un événement public à déclencher lorsque l'opération est terminée? Ensuite, l'appelant pourrait simplement s'inscrire pour gérer l'événement et vous n'avez pas à vous soucier de transmettre des objets ou des délégués.

L'objet implémentant une interface que vous avez fournie fonctionnerait, mais il semble que ce soit plus l'approche Java que l'approche .NET. Les événements me semblent un peu plus propres.

+0

Je ne sais pas comment faire des événements ... – Malfist

+0

Voir http://pobox.com/~skeet/csharp/events.html pour en savoir plus sur les événements. Ils mai mai ou ne pas convenir à votre situation, mais ils valent la peine d'être informés. –

-2

Vous pouvez utiliser System.Action disponible en C# .NET pour les fonctions de rappel. Veuillez vérifier cet exemple d'exemple:

//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

Ce n'est pas une alternative à un rappel; que ** est ** un rappel. – Servy