In Java you can do this:
protected void makeRequest<T extends BaseJsonClass, T2 extends BaseJsonClass> (Response<T> response, T2 dataToSend, String url) {}
Some request:
makeRequest(response, null, serverUrl);
makeRequest(response, jsonData, serverUrl);
In C# how?
I'm writing a method that should be able to accept data as null or as a specific type of object.
/**
* Make a request to the server.
* dataToSend can be null.
* */
protected void makeRequest<T, T2>(Response<T> response, T2 dataToSend, string url) where T : JsonObjectBase where T2 : JsonObjectBase
{ }
Currently I'm getting the problem:
The type arguments for method `BaseModelController.makeRequest<T,T2>(Response<T>, T2, string)'
cannot be inferred from the usage. Try specifying the type arguments explicitly
How would I allow a generic that can possibly be null as well?
** EDIT 1 **
I invoke this method like so:
makeRequest(response, null, serverUrl);
or
makeRequest(response, someJsonData, serverUrl);
** EDIT 2 **
JsonObjectBase is just an object that is extended by other Json classes so I can parse/serialize them auto-magically knowing that it will always be a Json object. I use it for type checking so other coders don't make the mistake of entering an unknown object.
Passing null is really much better than defining the same value which is 'suppose' to not do anything; because that gets messy very fast.
Example of the power
ModelControllerAccount.getInstance().createUser(
username.text, password.text, // Params
new Response<JsonUserAccountFeedback>(
success: (jsonObjectStandardResponse) => Debug.Log("Success when creating account. Data: " + jsonObjectStandardResponse.getAccessToken()),
failed: (failedReason) => Debug.Log("Failed to make request. Reason: " + failedReason.getReasonDescription())
)
);
If you can change the API somewhat, one easy way to fix this would be to add an overload that omits the second parameter. This is easier for the caller too in cases where you're not sending any data.
Like this:
protected void makeRequest<T>(Response<T> response, string url) where T : JsonObjectBase
{
makeRequest (response, default(JsonObjectBase), url);
}
Since you're most likely only need access to the methods of JsonObjectBase you could do something like this:
protected void MakeRequest<T>(Response<T> response, JsonObjectBase dataToSend, string url) where T : JsonObjectBase
{
}
and call the method like this: MakeRequest(response, null, serverUrl);
Or you could even take advantage of optional arguments:
protected void MakeRequest<T>(Response<T> response, string url, JsonObjectBase dataToSend = null) where T : JsonObjectBase
{
}
and call the method like this: MakeRequest(response, serverUrl);
This happens because a value of null doesn't tell the compiler the type of that parameter. After all, the implementation of makeRequest could check the type of T2 and do wildly different things depending on what it sees. If you had passed, say, a variable with the type of List<int>, it would know that T2 is List<int>, but null could be the value of any reference type. If the compiler can't figure out the type (or if it ever decides the wrong one), you'll need to tell it:
Response<string> myResponse;
makeRequest<Response<string>, object>(myResponse, null, "http://example.com");
I've just specified the types used to call the generic method. In this case, the type of the null parameter is object.
Related
I am trying to stub a RestClient to return a specific response for a specific request, which is recognized by checking the end of the URL that is used. This is the code I have come up with:
_clientStub = Substitute.For<IRestClient>();
_responseStub = Substitute.For<IRestResponse>();
_clientStub
.Get(
Arg.Is<IRestRequest>(
request => request.Resource.EndsWith("config.json")
)
)
.Returns(_responseStub);
I receive a NullReferenceException for the Arg.Is<IRestRequest> part and if I try to save it in a variable for reuse like this the variable evaluates to null:
protected static readonly IRestRequest CONFIG_QUERY =
Arg.Is<IRestRequest>(
request => request.Resource.EndsWith("config.json")
);
I was following the second example in the documentation so I am not exactly sure what is going wrong. Any help?
Clarification
For reproducability I created a minimal example:
[Fact]
public void StackOverflowTest()
{
RestSharp.IRestClient clientStub = Substitute.For<RestSharp.IRestClient>();
RestSharp.IRestResponse responseStub = Substitute.For<RestSharp.IRestResponse>();
clientStub
.Get(
Arg.Any<RestSharp.IRestRequest>()
)
.Returns(responseStub);
}
Yes, there are no assertions in this test. I don't even get to them anyways since the last command already throws and NullReferenceException. The interfaces are from RestSharp, but that should not really matter.
Update
To narrow the problem down I created an even simpler example and now it works:
public interface IStackOverflowResponse { };
public interface IStackOverflowRequest { };
public interface IStackOverflowClient
{
IStackOverflowResponse Get(IStackOverflowRequest request);
}
[Fact]
public void StackOverflowTest()
{
IStackOverflowClient clientStub = Substitute.For<IStackOverflowClient>();
IStackOverflowResponse responseStub = Substitute.For<IStackOverflowResponse>();
clientStub
.Get(
Arg.Any<IStackOverflowRequest>()
)
.Returns(responseStub);
}
So now I guess that there is a specific problem with mocking RestSharp.RestClient. I guess the problem lies with mocking/stubbing extension methods as the IRestClient does not have a Get method by itself, but instead there is an extension method for it.
The problem lies with the Get function of IRestClient... as it has none. This is just an extension method in RestClientExtensions. As you can see in the source code it simply calls Execute with Method.GET as parameter. So the correct way to stub
clientStub
.Get(
Arg.Any<RestSharp.IRestRequest>()
)
.Returns(responseStub);
is to do this:
clientStub
.Execute(
Arg.Any<RestSharp.IRestRequest>(),
Method.GET
)
.Returns(responseStub);
I am trying to build a generic extension method that can call a member function of a class dynamically and return a specified type. For some background, this is the general problem:
I am using Autorest to generate some client libraries for a swagger API. Because some GET routes within the API return different objects depending on the HTTP status code of the response, the method invocation returns object and the developer is responsible for casting the object themselves. I am trying to create a convenient wrapper for doing this cast in a generic way.
Here is an example of a typical function signature that would be wrapped up:
object IPet GetPets(string petName)
Note that this method might return a number of object types, depending on the HTTP status code. For instance, 200 might return a Dog object but 404 might return a Cat object.
This would be invoked through an Autorest generated client library like this:
AnimalApi animalClient = new AnimalApi(new Uri("http://myanimals.com"));
object pet = animalClient.Pet.GetPets("dog");
if(pet is Dog) {
Console.WriteLine("Dog!");
} else {
Console.WriteLine("Not Dog");
}
I would like to scoop up this manual casting functionality into something a bit more intuitive, here is what I am thinking:
AnimalApi animalClient = new AnimalApi(new Uri("http://myanimals.com"));
string petType = "Dog";
Dog pet = animalClient.Pet.CallMethod<IPet, Dog, string>( (api,type) => api.GetPets(type), petType);
In this scenario, any return other than objects of type 'Dog' would cause an exception to be thrown. Here is my attempt at implementation:
public static Tout CallMethod<Tin, Tout>(this Tin client, Expression<Action<Tin, Targ>> apiCall, params object[] args)
where Tout : class {
MethodCallExpression providedMethod = apiCall.Body as MethodCallExpression;
if(providedMethod == null) {
throw new ApplicationException("Invalid method call provded");
}
var method = providedMethod.Method;
object responseData;
try {
// Call object-returning function
responseData = method.Invoke(client, args);
} catch(Exception error) {
if(error.InnerException is HttpOperationException) {
// Unknown error occurred
var ex = error.InnerException as HttpOperationException;
object content = JsonConvert.DeserializeObject(ex.Response.Content);
throw new ServiceException(ex.Response.StatusCode + ": "
+ JsonConvert.SerializeObject(content));
} else {
throw error.InnerException;
}
}
// Return formatted object if successful
if(responseData is Tout) {
return responseData as Tout;
// Otherwise throw
} else {
// Deal with known error object responses
if(responseData is ErrorResponse) {
var error = responseData as ErrorResponse;
throw new ServiceException(error);
} else {
// Unknown error occurred
throw new ServiceException("Unknown response was received: "
+ JsonConvert.SerializeObject(responseData));
}
}
}
The problem I have here is of passing the function and arguments into the generic extension method. Without knowing the various possible numbers of arguments that might be required by the various API calls, how can I define Expression<Action<Tin, Targ>> generically? It seems to me like I would have to replicate this function with Expression<Action<T1, T2, T3>> and so on to accommodate varying length argumen lists.
I want an expressive way for people to interact with the API, such that it is easy to see what is happening. However, this mechanism should be robust to various API changes down the road. My current goal is to provide a way to encapsulate common object casting and error checking operations. Is there a better way to do this? For the moment I am working under the assumption that the server side swagger doc cannot change.
I'm using the RestSharp library to access a REST API.
I want all the API requests to go through the same method, so I can add headers, handle errors and do other stuff in a central place.
So I made a method that accepts a generic Func<> and that solves most of my problems, but I don't know how to handle the case where I don't have a return type.
private T PerformApiCall<T>(RestRequest restRequest, Func<RestRequest, IRestResponse<T>> restMethod)
{
var response = restMethod.Invoke(restRequest);
//handle errors
....
return response.Data;
}
I call it like this:
var apples = PerformApiCall(new RestRequest('/api/apples'), req => Client.Execute<List<Apple>>(req));
But I came across a problem, a bunch of API calls don't have a return type because they don't return data. So I used Client.Execute(req) and I get the error saying the type arguments cannot be inferred, I tried to pass , but that failed because it couldn't convert the non-generic IRestResponse to the typed one.
Any ideas on how to tackle this in a nice way?
One thing you could try is to add an overload to your PerformApiCall function that takes a Func with a non-generic result type, and returns nothing:
// Notice the `Func` has `IRestResponse`, not `IRestResponse<T>`
public void PerformApiCall(RestRequest restRequest,
Func<RestRequest, IRestResponse> restMethod)
...
Then, depending on how complex your error checking/logic is, you could move it out to a separate method (which returns the response), and call it from both overloads of PerformApiCall:
private T PerformRequestWithChecks<T>(RestRequest restRequest,
Func<RestRequest, T> restMethod)
where T : IRestResponse
{
var response = restMethod.Invoke(restRequest);
// Handle errors...
return response;
}
// You can use it from both versions of `PerformApiCall` like so:
//
// // From non-generic version
// var response =
// PerformRequestWithChecks<IRestResponse>(restRequest, restMethod);
//
// // From generic version
// var response =
// PerformRequestWithChecks<IRestResponse<T>>(restRequest, restMethod);
// return response.Data;
You were getting a compiler error because it is sound to treat a subtype as if it was an instance of its supertype, but it is not sound to do it in the other direction (which is what was happening when you changed your calling code to just Client.Execute(req), returning a non-generic).
Here's an ideone paste illustrating this: http://ideone.com/T2mQfl
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
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.
http://www.blackwasp.co.uk/FuncAction.aspx
Func vs. Action vs. Predicate
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);
}
}
}
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);
I want to chain together two (and possibly more in the future) methods to a delegate and just wondered if there is a way to do this in one assignment statement, e.g.
I have a delegate method signature defined as
public delegate void MaskRequestSection(Request request);
...and 2 methods that use this signature, namely...
public void MaskCvnSection(Request request)
{
// do the masking operation
}
public void MaskCardNumberSection(Request request)
{
// do the masking operation
}
At present, I am using the following to instantiate the delegete, chain the 2 methods to it and then invoke them...
private void HideDetailsInRequest(Request request)
{
MaskRequestSection maskRequestSection = MaskCvnSection;
maskRequestSection += MaskCardNumberSection;
maskRequestSection(request);
}
....I am just curious as to why I can't chain both delegates in one statement like below,
MaskRequestSection maskRequestSection = MaskCardNumberSection+ MaskCvnSection;
...but also if there is another way that it can be done within one declaration. I haven't been able to find anything that specifically addresses this on MSDN, and I'm just asking for my own curiosity.
Thanks in advance.
You can do it with a cast:
var maskRequestSection = (MaskRequestSection) MaskCardNumberSection
+ (MaskRequestSection) MaskCvnSection;
... but you can't do it without one, because the + operator here works on delegates, not method groups. When the compiler sees the binary + operator, it has to work out the type of the expression, and that doesn't take the assignment part into account.