StrataFrame Forum

How to pass a method as a parameter

http://forum.strataframe.net/Topic30263.aspx

By Ger Cannoll - 8/23/2011

I want to set up a General Purpose type method which will have two parameters, a Business Object, and a Method Name of the business object. The method then needs to just run the method.

e.g.

private void RunABoMethod(BusinessObject myBo, Methodname MyMethodname))
{
      myBO.MyMethodname;
}
so some examples of how this might be called:
RunABoMethod(CustomerBO,"GetAllrecords");
or
RunABomethod(StockBO,"GetTop20");


Any suggestions / coding examples on how this might be accomplished (c#) would be appreciated. A few searches indicate that Func (Dot Net 3.5) or delgates could be used but I have no experience of using these constructs
By Edhy Rijo - 8/23/2011

Hi Gerard,

Based on your sample, it looks like you want to have a set of methods to be able to use them from any BO.  If that is the case, then it is pretty simple:
  1. Create a BO base class and inherit it from MicroFour.StrataFrame.Businesss.BusinessLayer
  2. Add any public methods you want to be available to all BOs.
  3. Inherit the base BO in any new BO and use your methods.
Here is a sample code I have on my Base BO.  I use VB.
    ''' <summary>
     ''' This method will return all records from this BO TableName.
     ''' </summary>
     ''' <remarks></remarks>
     Public Overridable Sub FillAllRecords()
         Using cmd As New SqlCommand()
             cmd.CommandType = CommandType.Text
             cmd.CommandText = String.Format("Select * From {0}"Me.TableNameAndSchema)
             '-- Set the ORDER BY clause if filled.
             If Not String.IsNullOrEmpty(Me.SortColumnFieldList) Then
                 cmd.CommandText += " ORDER BY " & Me._SortColumnFieldList
             End If
             Me.FillDataTable(cmd)
         End Using
     End Sub

Now when I create a new BO I inherit the base BO class, will have access to the FillAllRecords() method, and since it is "Overridable", I can even overrite it at any subclass level.

Public Class bizItems
     Inherits CardTrackingSystem.Business.ApplicationBaseBusinessClass
... more code here....
End Class


Hope this help!
By Ger Cannoll - 8/30/2011

Hi Edhy , thanks for your reply.

I have implemented your suggestion and changed my code around a bit, and it works fine, as long as method name is the same, and I am over-riding a spefic method.

What I was trying to get at , was a way of running a method, but the method name may be different, really a way of passing a method name as a parameter, and then running the 'passed' method.  Each BO could  have a different method name and I am trying to pass the Bo and method name to a general purpos type routine.

Say for instance I have a Cutomers BO with a method called CalculateCustomers and a Stock BO with a Method called CalculateStock. I then want to pass a BO and a method name to a Routine which will execute the Method I have called on the Bo I have called.

So I might RunMyMethod(CustomerBO,"CalculateCustomers")      or   RunMyMethod(StockBO,"CalculateStock") and Pseudo code for RunMyMethod would be:

RunMyMethod(MicroFour.StrataFrame.Business.BusinessLayer MyBo, string MyMethodName)
{ BO.MyMethodName() }


The end result of this is to run the CalclateCustomers method in the CustomersBO  or run the CalculateStock in the StockBO etc
By Edhy Rijo - 8/30/2011

Hi Gerard,

I see what you meant now.  I have not done that, but my guess is that you would have to use the Reflection class or something like lazy binding,  to sort of been able to execute the method in the passed BO.  Also you must CAST your bo to the proper type to be able to find your method name, this could get ugly.

Probably looking at your logic from a different side you can achieve this easier.  Using your sample, you will always know at some point which BO and Method you want to run, so unless this must be totally generic and data driven, you can simply have an Enumeration listing the pre-existing methods and just use the old Select Case MyEnumeration and just pre-code your BO method calling. 
Again, this may not be generic enough for your needs, but could be faster, easier and safe. Doze
By Ger Cannoll - 8/30/2011

Hi Edhy.

Yes, I was trying to make this fairly Generic, though I see your  point about using an enumeration as a possible way to go.

I think this can be done using Delegates and/or functions , just have no experience of using them... perhaps someone familiar with these might jump in.
By Keith Chisarik - 8/30/2011

You may want CallByName(). I have found it useful in doing something similar to what you describe. I have a project where just about everything is data driven, I use CallByName to execute methods whos names are stored in a table, as they are assigned by the user from a set of selections, very much like a query builder, so the value of the field "StuffToDoToSomeString" might be "TrimIt()" or "SplitCamelCase()", or ... you get the idea. Hope this might help you.

http://msdn.microsoft.com/en-us/library/chsc1tx6(v=vs.80).aspx
By Edhy Rijo - 8/30/2011

Hi Keith,
Thanks for the information, very interesting function.
By Ger Cannoll - 9/3/2011

Hi Keith . Thats exactly waht I want to do.

Unfortunately, CallByName seems to be a VB thing.. not supported in C#, but reflection and INVOKE seems to do it in C#