2009-03-20 11 views
15

Chcę mieć bibliotekę, która będzie zawierała funkcję, która akceptuje obiekt dla jego parametru.Oddzwonienia w C#

Przy pomocy tego obiektu chcę móc wywołać określoną funkcję po zakończeniu X. Wywoływana funkcja ma być określona przez wywołującego, a X zostanie wykonane i monitorowane przez bibliotekę.

Jak mogę to zrobić?

Dla odniesienia używam C# i .NET 3.5

+0

Podejrzewam, że Twoja odpowiedź zawiera degates, wydarzenia lub jedno i drugie. Jednak po kilkakrotnym przeczytaniu twojego pytania nie jestem w stanie objąć głowy tym, o co prosisz. – Brian

+1

Oto przykład http://blog.jerrynixon.com/2011/11/there-are-lots-of-things-that-take-long.html –

Odpowiedz

38

delegata i użyć anonimowego delegata lub lambda wyrażenie

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

Albo użyć interfejsu

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

dany obiekt musi implementować interfejs dostarczony przez ciebie. Przyjmij interfejs jako parametr, a następnie możesz wywołać dowolną metodę udostępnianą przez interfejs. W przeciwnym razie nie masz możliwości dowiedzenia się, do czego ten obiekt jest zdolny. To lub możesz wziąć delegata jako parametr i wywołać to.

+0

To jest dokładnie poprawne. – plinth

6

Brzmi jak doskonały przepis na delegatów - w szczególności połączenia zwrotne z delegatami są dokładnie takie, jak to jest obsługiwane w asynchronicznym wzorze w .NET.

Osoba dzwoniąca zwykle przekazuje ci pewien stan i delegata, i przechowujesz oba w dowolnym kontekście, a następnie dzwoni się do delegata przekazującego mu stan i wynik, jaki możesz mieć.

Można albo ustawić stan jako object, albo potencjalnie użyć delegata ogólnego i przyjąć stan odpowiedniego typu, np.

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

Następnie:

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

Jak używasz .NET 3.5 możesz wykorzystać istniejące Func<...> i Action<...> typy delegata, ale może znaleźć to sprawia, że ​​jaśniejsze zadeklarować Twój własny. (Nazwa może sprawić, że będzie bardziej przejrzysty dla tego, czego używasz).

+2

Sugeruję, abyś przeczytał wtedy delegatów (i generycznych, potencjalnie). Mój artykuł na temat delegatów i ewangelistów znajduje się na http://pobox.com/~skeet/csharp/events.html –

1

Czy istnieje powód, dla którego biblioteka nie powinna wywoływać zdarzenia publicznego po zakończeniu operacji? Następnie osoba dzwoniąca może po prostu zarejestrować się, aby obsłużyć zdarzenie i nie musisz się martwić o przekazywanie obiektów lub delegatów.

Obiekt implementujący dostarczony interfejs będzie działał, ale wydaje się być bardziej podejściem Java niż podejście .NET. Wydarzenia wydają mi się nieco bardziej ekologiczne.

+0

Nie wiem, jak robić wydarzenia ... – Malfist

+0

Zobacz http://pobox.com/~skeet/csharp/events.html, aby poznać wydarzenia. Mogą, ale nie muszą być odpowiednie dla twojej sytuacji, ale warto o nich wiedzieć. –

-2

Można użyć System.Action dostępne w C# .NET dla funkcji zwrotnych dostaw. Sprawdź przykładowy przykład:

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

To nie jest alternatywa dla oddzwaniania; ** to ** wywołanie zwrotne. – Servy

Powiązane problemy