Reputation: 197
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
Upvotes: 0
Views: 1670
Reputation: 12540
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);
}
}
}
Upvotes: 1
Reputation: 5197
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);
Upvotes: 0