0

I am writing an HTTP wrapper class object in C# and I would like to give the main method the ability to receive a function as a parameter and then execute it on the source HTML returned by the POST/GET.

For example I may want to pass a function that checks the headers for a cookie and only returns true if it's found OR pass a regular expression function that checks the source for a piece of content.

I know in PHP or JS I could easily just pass functions as parameters but I am not sure on how to go about it without creating delegates that match the functions I want to use.

I would like the code to be as "generic" as possible so that it could receive any function e.g Pseudocode would be like

public bool MakeHTTPRequest(string url, object possiblefunction)
{

   make HTTP request

   if status == 200
   {

    string response = getresponse

    if(object is function){

        call object
    }
  }
}

So the function may OR may NOT be passed in, or I may set a global property with it. Then I need to check IF a function exists and execute it if it does.

The function could be ANYTHING and I want to future proof the code so it can handle any kind of function in the future that maybe passed to it.

Any help would be much appreciated.

Thanks

user2334626
  • 197
  • 1
  • 1
  • 12
  • Use Action, Action, etc.... – Colin Smith Aug 30 '13 at 12:39
  • Or if the function returns something: [Func< TResult >](http://msdn.microsoft.com/library/bb534960.aspx), Func, etc. - the thing is, actions or functions might need parameters (the `T`s here). You won't be able to just "call" an action or function without parameters if it needs them. – Corak Aug 30 '13 at 12:41
  • It's commonly bad practice to use the datatype object in the method signature. You can do it but you're going to need to implement a lot of exception handling. – Brandon Aug 30 '13 at 12:48

2 Answers2

1

Use either Func or Action (or Predicate as mentioned by DavidN) to specify the contract of delegates passed as a parameter into your MakeHTTPRequest method.

public bool MakeHTTPRequest(string url, Action possiblefunction)
{

   make HTTP request

   if status == 200
   {

    string response = getresponse

    if(possiblefunction != null){

        possiblefunction();
    }
  }
}

If your "function" returns a value/result then use Func instead..(where T is the expected return type)...e.g. Func<int>.

If your "function" expects parameters then specify the expected parameter types. So here are some examples:

Func<string,float,int> - a delegate which expects string and float parameters and returns an int result

Action - a delegate that takes no parameters, and doesn't return a value

Action<string,float> - a delegate that doesn't return a value (void), and expects a string and float as parameters.

If you're trying to pass back the "response" to the possiblefunction then do something like this.

public bool MakeHTTPRequest(string url, Action<string> possiblefunction)
{

   make HTTP request

   if status == 200
   {

    string response = getresponse

    if(possiblefunction != null){

        possiblefunction(response);
    }
  }
}
Community
  • 1
  • 1
Colin Smith
  • 12,375
  • 4
  • 39
  • 47
  • If it is `MakeHTTPRequest(string url, object possiblefunction)` then you can test `var action = possiblefunction as Action; if (action != null) { action(); }` – Corak Aug 30 '13 at 12:49
0

Based on the examples you've given, it seems that what you really want is to pass in a set of validators to determine if the HTTP response meets certain criteria. This seems to be further corroborated by the fact that your method is returning bool.

A Predicate<T>, or actually a set of Predicates, should encapsulate criteria rules that you pass in to determine whether the request is valid or not.

The signature for a Predicate<T> is bool Predicate<T>(T t) - meaning that it takes in some type and produces a bool

Using an array of predicates, and making sure they all pass, seems to be a pretty future-proof way for what you want to do

public bool MakeHTTPRequest(string url, params Predicate<WebResponse>[] validators)
{    
   // make HTTP requrest

   var request = HttpWebRequest.Create(url);
   var response = (HttpWebResponse)request.GetResponse();

   if (response.StatusCode == HttpStatusCode.OK){
        foreach(var validator in validators)
            if (!validator(response))
                return false;
   }

    return true;    
}

The trick is that the params keyword allows you to call the method passing in [0..any number] of values for the params, so all of the following invocations would work:

MakeHTTPRequest("http://stackoverflow.com");
MakeHTTPRequest("http://stackoverflow.com", r => r.Headers.AllKeys.Contains("CookieHeader"));
MakeHTTPRequest("http://stackoverflow.com", r => r.Headers.AllKeys.Contains("CookieHeader"), r => r.ContentLength < 10000);
DavidN
  • 5,117
  • 2
  • 20
  • 15
  • Wicked, just what I wanted. Yes you are right. I want to pass in any number of functions that validate the response yet I don't know how many or what they might contain at design time. An array of functions/validators is just what I need. Thanks! – user2334626 Aug 30 '13 at 14:16
  • quick question, I notice most of those validators are simple boolean tests. What if I wanted to pass in as a validator a function that did multiple checks, ORS, or complex checking not just a simple IF A AND B AND C. So a function that checks multiple criteria and if true, then further checks are done or not done before returning true/false. So something a bit more complex than is the length of content < 1000 or does a cookie exist etc. – user2334626 Sep 02 '13 at 10:52