2009-03-20 18 views
15

Voglio avere una libreria che avrà una funzione in esso che accetta un oggetto per il suo parametro.Chiamate in C#

Con questo oggetto voglio essere in grado di chiamare una funzione specificata quando X è finito. La funzione che verrà chiamata deve essere specificata dal chiamante e X verrà eseguita e monitorata dalla libreria.

Come posso fare questo?

Per riferimento sto usando C# e .NET 3.5

+0

Sospetto che la risposta contenga gradi, eventi o entrambi. Tuttavia, dopo aver letto la tua domanda un paio di volte, non sono in grado di comprendere ciò che stai chiedendo. – Brian

+1

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

risposta

38

Fornitura un delegato e utilizzare un delegato anonima o 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")); 
} 

Oppure utilizzare un'interfaccia

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'oggetto in questione sarà necessario implementare un'interfaccia fornito da voi. Prendi l'interfaccia come parametro e quindi puoi chiamare qualsiasi metodo esposto dall'interfaccia. Altrimenti non hai modo di sapere di cosa sia capace l'oggetto. Quello, o potresti prendere un delegato come parametro e chiamarlo.

+0

Questo è esattamente corretto. – plinth

6

Suona come una ricetta perfetta per i delegati - in particolare, i callback con i delegati sono esattamente come questo viene gestito nel modello asincrono in .NET.

Il chiamante di solito ti passa qualche stato e un delegato, e li memorizzi entrambi in qualsiasi contesto tu abbia, quindi chiama il delegato passandogli lo stato e qualsiasi risultato tu possa avere.

È possibile creare lo stato solo object o potenzialmente utilizzare un delegato generico e assumere lo stato del tipo appropriato, ad es.

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

Poi:

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

Come stai usando .NET 3.5 si potrebbe desiderare di utilizzare le Func<...> e Action<...> tipi di delega esistente, ma si può trovare lo rende più chiaro per dichiarare il tuo. (Il nome potrebbe rendere più chiaro il motivo per cui lo stai utilizzando.)

+2

Ti suggerisco di leggere i delegati (e generici, potenzialmente). Il mio articolo su delegati ed evvents è su http://pobox.com/~skeet/csharp/events.html –

1

C'è un motivo per cui la tua libreria non deve fornire un evento pubblico da attivare quando l'operazione è completata? Quindi il chiamante potrebbe registrarsi per gestire l'evento e non dovrai preoccuparti di passare oggetti o delegati.

L'oggetto che implementa un'interfaccia fornita funzionerebbe, ma sembra essere più l'approccio Java che l'approccio .NET. Gli eventi mi sembrano un po 'più puliti.

+0

Non so come fare eventi ... – Malfist

+0

Vedere http://pobox.com/~skeet/csharp/events.html per informazioni sugli eventi. Possono o meno essere appropriati per la tua situazione, ma ne vale la pena sapere. –

-2

È possibile utilizzare System.Action disponibile in C# .NET per le funzioni di callback. Si prega di verificare questo esempio di esempio:

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

Non è un'alternativa a una richiamata; quello ** è ** un callback. – Servy

Problemi correlati