Callbacks in C#

后端 未结 5 1398
孤独总比滥情好
孤独总比滥情好 2020-12-28 17:52

I want to have a library that will have a function in it that accepts an object for it\'s parameter.

With this object I want to be able to call a specified function

相关标签:
5条回答
  • 2020-12-28 18:23

    You can use System.Action available in C#.NET for callback functions. Please check this sample example:

        //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 讨论(0)
  • 2020-12-28 18:24

    Two options for you:

    1. Have the function accept a delegate (Action for a callback that doesn't return anything, Func for one that does) and use an anonymous delegate or Lambda Expression when calling it.

    2. Use an interface

    Using a delegate/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"));
    }
    

    If your callback needs to have something passed to it, you can use a type parameter on Action:

    public static void DoWork(Action<string> processAction)
    {
      // do work
      if (processAction != null)
        processAction("this is the string");
    }
    
    public static void Main()
    {
      // using anonymous delegate
      DoWork(delegate(string str) { Console.WriteLine(str); });
    
      // using Lambda
      DoWork((str) => Console.WriteLine(str));
    }
    

    If it needs multiple arguments, you can add more type parameters to Action. If you need a return type, as mentioned use Func and make the return type the last type parameter (Func<string, int> is a function accepting a string and returning an int.)

    More about delegates here.

    Using an 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);
    }
    
    0 讨论(0)
  • 2020-12-28 18:27

    Sounds like a perfect recipe for delegates - in particular, callbacks with delegates are exactly how this is handled in the asynchronous pattern in .NET.

    The caller would usually pass you some state and a delegate, and you store both of them in whatever context you've got, then call the delegate passing it the state and whatever result you might have.

    You could either make the state just object or potentially use a generic delegate and take state of the appropriate type, e.g.

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

    Then:

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

    As you're using .NET 3.5 you might want to use the existing Func<...> and Action<...> delegate types, but you may find it makes it clearer to declare your own. (The name may make it clearer what you're using it for.)

    0 讨论(0)
  • 2020-12-28 18:31

    Is there a reason not to have your library provide a public event to be fired when the operation is complete? Then the caller could just register to handle the event and you don't have to worry about passing around objects or delegates.

    The object implementing an interface you have provided would work, but it seems to be more the Java approach than the .NET approach. Events seem a bit cleaner to me.

    0 讨论(0)
  • 2020-12-28 18:46

    The object in question will need to implement an interface provided by you. Take the interface as a parameter, and then you can call any method that the interface exposes. Otherwise you have no way of knowing what the object is capable of. That, or you could take a delegate as a parameter and call that.

    0 讨论(0)
提交回复
热议问题