Обратные вызовы в C#
Я хочу иметь библиотеку, в которой будет функция, которая принимает объект для его параметра.
с этим объектом я хочу иметь возможность вызывать указанную функцию, когда X будет завершен. Вызываемая функция должна быть задана вызывающим объектом, А X будет выполняться и контролироваться библиотекой.
Как я могу это сделать?
для справки я использую C# и .NET 3.5
5 ответов
предоставьте делегат и используйте анонимный делегат или лямбда-выражение
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"));
}
или использовать интерфейс
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);
}
звучит как идеальный рецепт для делегатов - в частности, обратные вызовы с делегатами-это именно то, как это обрабатывается в асинхронном шаблоне.Сеть.
вызывающий обычно передает вам некоторое состояние и делегат, и вы сохраняете оба из них в любом контексте, который у вас есть, а затем вызываете делегата, передающего его состояние и любой результат, который у вас может быть.
вы могли бы либо сделать государство просто object
или потенциально использовать универсальный делегат и принять состояние соответствующего типа, например,
public delegate void Callback<T>(T state, OperationResult result)
затем:
public void DoSomeOperation(int otherParameterForWhateverReason,
Callback<T> callback, T state)
поскольку вы используете .NET 3.5, вы можете использовать существующий Func<...>
и Action<...>
делегировать типы, но вы мая найти это делает его более четким, чтобы объявить свой собственный. (Название может прояснить, для чего вы его используете.)
объект в вопрос нужно реализовать интерфейс, предоставленный вам. Возьмите интерфейс в качестве параметра, а затем вы можете вызвать любой метод, который предоставляет интерфейс. Иначе вы не сможете узнать, на что способен объект. Это, или вы можете взять делегат в качестве параметра и вызвать это.
есть ли причина, по которой ваша библиотека не предоставляет публичное событие для запуска после завершения операции? Затем вызывающий абонент может просто зарегистрироваться для обработки события, и вам не нужно беспокоиться о передаче объектов или делегатов.
объект, реализующий интерфейс, который вы предоставили, будет работать, но, похоже, это больше подход Java, чем подход .NET. События кажутся мне чище.
вы можете использовать системы.Действия, доступные в C#.NET для функций обратного вызова. Пожалуйста, проверьте этот пример:
//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);
}
}