Sunday, August 25, 2013

of handing in delegates to APIs

Chapter 25 of C# in a Nutshell is basically on interfacing with C++ from C#, and it really isn't that interesting. However!, there is an example in which a C++ method signature takes in a C# delegate which I found fascinating. Not caring too much about C++, I imagined how a C# library might consume a Func from another outside C# method in a different library that might use the API taking the Func.

using System;
namespace Whatever.Core
{
   public static class Api
   {
      public static int AddThreeNumbers(Func<int> middleAct)
      {
         int counter = 0;
         counter = counter + 1;
         counter = counter + middleAct();
         counter = counter + 2;
         return counter;
      }
   }
}

 
 

So, why hand in a Func? Can't the thing using the API do whatever it needs to do that is extra after the API call runs? Well, I can think of a few reasons for something like this. At work, we are struggling to find a way to swap the asset child of an asset with another child in Oracle's eBusiness Suite through the API it exposes. It looks like we will have to make one API call to drop an association and then another that makes a new association. Well, what if something goes wrong between the two? What should be done? We could have an API that leaves that to the caller. Perhaps the caller could hand in another method from the API to attempt to associate anew the dropped child. Perhaps the caller could just log the problem, handing in a method that is rolled in the caller's project. In an alternative scenario, what if the API takes in a list of T and it will "process" each T? At the end of each processing it could run a Func that was handed in. As much would extend its capabilities!

using System;
using Whatever.Core;
namespace Whatever.UserInterface.Objects
{
   public class ApiManipulator
   {
      public int Number { get; set; }
      
      public ApiManipulator()
      {
         Number = 0;
      }
      
      private int DoSomethingFunky()
      {
         return 10;
      }
      
      public void CallOutToAnotherProject()
      {
         Func<int> somethingFunky = DoSomethingFunky;
         Number = Api.AddThreeNumbers(somethingFunky);
      }
   }
}

 
 

I've been impressed with how Action types are used in the observer pattern, but otherwise I never saw why I should care about functional programming. I didn't see why I might use a Func and indeed it does seem that they should be used sparingly. "I get it" a little better now.

using Whatever.UserInterface.Objects;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Whatever.Tests
{
   [TestClass]
   public class Test
   {
      [TestMethod]
      public void TestApiWrapper()
      {
         ApiManipulator apiManipulator = new ApiManipulator();
         Assert.AreEqual(apiManipulator.Number, 0);
         apiManipulator.CallOutToAnotherProject();
         Assert.AreEqual(apiManipulator.Number, 13);
      }
   }
}

No comments:

Post a Comment