Can we make this method generic? - c#

I saw this method in a sample from Xamarin, using JSON accessing a REST Server:
List<Country> countries = new List<Country>();
public Task<List<Country>> GetCountries()
{
return Task.Factory.StartNew (() => {
try {
if(countries.Count > 0)
return countries;
var request = CreateRequest ("Countries");
string response = ReadResponseText (request);
countries = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Country>> (response);
return countries;
} catch (Exception ex) {
Console.WriteLine (ex);
return new List<Country> ();
}
});
}
where "CreateRequest" and "ReadResponseText" are methods that interact with a REST Server, basically receiving a list of countries to deserialize and return in the list.
So now, I'm trying to make this method generic in order to receive the type and return a generic list of objects of the specified type, something like this:
public static Task<List<Object>> getListOfAnyObject(string requested_object, Type type)
{
return Task.Factory.StartNew (() => {
try {
var request = CreateRequest (requested_object);
string response = ReadResponseText (request);
List<Object> objects = // create a generic list based on the specified type
objects = Newtonsoft.Json.JsonConvert.DeserializeObject<List<Object>> (response); // not sure how to handle this line
return objects;
} catch (Exception ex) {
Console.WriteLine (ex);
return ex.Message;
}
});
}
So my question is, how can I create the method above in order to use it more and less like this (casting the list to my desired type)?
List<Country> countries = (List<Country>)(List<?>) getListOfAnyObject("countries",Country.type);
Many thanks in advance!

Try something like this..
public static Task<List<T>> getListOfAnyObject<T>(string requested_object)
{
return Task.Factory.StartNew (() => {
try {
var request = CreateRequest (requested_object);
string response = ReadResponseText (request);
return Newtonsoft.Json.JsonConvert.DeserializeObject<List<T>> (response); // not sure how to handle this line
} catch (Exception ex) {
Console.WriteLine (ex);
return ex.Message;
}
});
}
Called like so..
List<Country> countries = getListOfAnyObject<Country>("countries");

Related

Xamarin.Forms Service return List<T> plus Status Code

This is the code from the service i generated.Everything work fine. I get the list of photos, but i want to get the status_code and make logic in the ViewModel and show message to the user.
public async Task<IList<Photo>> GetAllPosts()
{
try
{
if (CrossConnectivity.Current.IsConnected)
{
instagramCloneClient.DefaultRequestHeaders.Clear();
instagramCloneClient.DefaultRequestHeaders.Add("Accept", "application/json");
var response = await instagramCloneClient.GetAsync($"/photos");
var status_code=(int)response.StatusCode;
if (response.IsSuccessStatusCode)
{
string jsonMessage;
using (Stream responseStream = await response.Content.ReadAsStreamAsync())
{
jsonMessage = new StreamReader(responseStream).ReadToEnd();
}
IList<Photo> photos = JsonConvert.DeserializeObject<IList<Photo>>(jsonMessage);
return photos;
}
else
{
return null;
}
}
else
{
return null;
}
}
catch (Exception ex)
{
Debug.WriteLine(ex);
string error = ex.Message;
return null;
}
}
I return list of photos. I also want response.StatusCode to the ViewModel from which i call the function.I must return IList, how to include some int status_code? What is the best practice?
You have multiple options. You can create a new model with your List and an integer/enum for the StatusCode. Another option is to return a List of ArrayList.

How to do async await function imports/SP EF6

I have a function imports a stored procedure, but I want to make it as async. How could I do that?
Any ideas?
public static async Task<List<ObtenerLayoutPor_Result>> GenerarArchivoPorBanco()
{
List<ObtenerLayoutPor_Result> result = new List<ObtenerLayoutPorBanco_Result>();
try
{
using (CobranzaEntities db = new CobranzaEntities())
{
return Task.Run(() => db.ObtenerLayoutPor(96)).GetAwaiter(); //one try
result = await db.ObtenerLayoutPor(96); //second try
}
}
catch (Exception ex)
{
throw new Exception(ex.Message);
}
return result;
}
I would do it like that:
public static Task<List<ObtenerLayoutPor_Result>> GenerarArchivoPorBanco()
{
return Task.Run(()=>{ // no await here and function as a whole is not async
using (CobranzaEntities db = new CobranzaEntities())
{
return db.ObtenerLayoutPor(96).ToList(); // depending on your implementation, ToList may be requiered to make the actual trip to database
}
});
}
or, as suggested in comment, if you stored procedure returns IQueryable, you can simply use this code:
public static Task<List<ObtenerLayoutPor_Result>> GenerarArchivoPorBanco()
{
using (CobranzaEntities db = new CobranzaEntities())
{
return db.ObtenerLayoutPor(96).ToListAsync();
}
}
To sum up, the easiest way to make a funtion async is to wrap it in Task.Run. Then you can use it in your code:
var results = await GenerarArchivoPorBanco();

Generic Function wrapper

I have many functions with different content but the parameters and try catch inside is almost similar. Is there anyway to wrap the function up so that can reduce redundant codes.
ResponseStatus GetPotatoList(GetPotatosRequest requestParam, out GetPotatosResponse response, out ResponseErrorType errorType)
{
ResponseStatus status = ResponseStatus.Fail;
response = new GetPotatosResponse();
//To Do
try
{
//To Do
status = ResponseStatus.Success;
}
catch(CustomException ex)
{
errorType = ResponseErrorType.CustomError;
}
catch(TimeoutException ex)
{
errorType = ResponseErrorType.Timeout;
}
catch(Exception ex)
{
errorType = ResponseErrorType.GeneralFailure;
}
return status;
}
You can pass an Action to your method.
ResponseStatus GetPotatoList(Action action1, Action action2, GetPotatosRequest requestParam, out GetPotatosResponse response, out ResponseErrorType errorType)
{
ResponseStatus status = ResponseStatus.Fail;
response = new GetPotatosResponse();
action1();
try
{
action2();
status = ResponseStatus.Success;
}
catch(CustomException ex)
{
errorType = ResponseErrorType.CustomError;
}
catch(TimeoutException ex)
{
errorType = ResponseErrorType.Timeout;
}
catch(Exception ex)
{
errorType = ResponseErrorType.GeneralFailure;
}
return status;
}
Then use it:
var response = GetPotatoList(
() => doSomething(),
() => doSomethingElse(),
requestParam,
out response,
out errorType);
I needed to provide functionality before and after invoking an original method whose signature didn't vary much.
I used Func<..>...
public static Func<string, string> Hello = name => "hello " + name;
public static string Hello2(string name) => wrap(Hello)(name);
// This does NOT retain the name of the arg for hints in the IDE
public static Func<string, string> Hello3 = name => wrap(Hello)(name);
private static Func<string, T> wrap<T>(Func<string, T> orig)
{
return name => orig(name.ToUpper());
}
Instead using Action you should maybe use a function that will take the request as the parameter and return your response object, then you can take benefit of generics to make the call and then handle specific cases. Also returning tuple or some generic type for the Result might be a good idea instead of using out parameters.
public static Tuple<TResponse, ResponseStatus, ResponseErrorType> GetResponse<TRequest, TResponse>(Func<TRequest, TResponse> action, TRequest request)
{
var status = ResponseStatus.Fail;
var errorType = ResponseErrorType.None;
var response = default(TResponse);
try
{
response = action(request);
status = ResponseStatus.Success;
}
catch (CustomException ex)
{
errorType = ResponseErrorType.CustomError;
}
catch (TimeoutException ex)
{
errorType = ResponseErrorType.Timeout;
}
catch (Exception ex)
{
errorType = ResponseErrorType.GeneralFailure;
}
return new Tuple<TResponse, ResponseStatus, ResponseErrorType>(response, status, errorType);
}

How to avoid code duplication inside two methods?

I have two identical methods, but one of them have return statement inside try catch
public void A(Guid agentId)
{
var agent = _agentsProvider.GetAgentById(agentId);
var updateCompletionSource = C(agentId);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, true, false);
updateCompletionSource.SetResult(cacheEntry);
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
}
}
private Entry B(IAgent agent)
{
var updateCompletionSource = C(agent.Id);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, false, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}
How to collect identical part and create new method with this part?
Unless GetPreviousCacheEntry could have problematic side-effects, it seems to me that you don't need method A at all.
Just call method B and ignore the return value if you're not interested in it.
As noted in comments, the methods aren't identical other than the return statements though - because they use a different second argument for UpdateAgentMetadataCacheEntry, and they have different parameters too (one has a Guid and one has an Agent). You could refactor this into:
private Entry B(IAgent agent, bool foo)
{
var updateCompletionSource = C(agent.Id);
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, foo, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}
... with a meaningful name for foo, obviously. I'll assume the difference in parameter type isn't a problem in reality.
Like Jon said, you don't need method A. Just add another parameter for boolean value.
public void A(Guid agentId)
{
var agent = _agentsProvider.GetAgentById(agentId);
AnotherA(agent, true);
}
private Entry B(IAgent agent)
{
return AnotherA(agent, false);
}
private Entry AnotherA(IAgent agent, bool a)
{
try
{
var cacheEntry = UpdateAgentMetadataCacheEntry(agent, a, false);
updateCompletionSource.SetResult(cacheEntry);
return cacheEntry;
}
catch (Exception e)
{
updateCompletionSource.SetException(e);
return GetPreviousCacheEntry();
}
}

Repeating code pattern

I have certain code pattern (which log performance and other variable for each function) which need to be present in every function, and I do not want to repeat the code over and over again. Here is what the code looks like:
public OutClass FUNC-X
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
/**
* THIS SINGLE LINE IS THE VARIABLE PART
**/
var output = dm.FUNC-X(...);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch (WebFaultException)
{
throw;
}
catch (OtherException ex)
{
if (Logger.IsErrorEnabled)
{
Logger.LogError("Exception in FUNC-X", ex);
}
throw new OtherException("Some Message");
}
catch (Exception ex)
{
if (IsErrorEnabled)
{
Logger("Exception in FUNC-X", ex);
}
throw new Exception("Generic Exception");
}
finally
{
if (IsDebugEnabled)
{
Logger("End FUNC-X");
}
}
}
Essentially, I just need to replace FUNC-X with FUNC-Y or FUNC-Z everywhere this name occurs, is there some kind of design pattern which I can follow?
I'm sorry if the question is vague, I shall be happy to provide any details you ask.
Yeah, there are many ways to provide nice log code.
Use aspect-oriented programming. There is PostSharp and Spring.NET. You can use log4net library. All of them after config supports writing of method name.
You can use T4 and generate code for all funcs before compile.
You can write one global logging method that accepts Func<object> method and string methodName. Suppose you named your logging method LogAndExecute. Then to call you must write smth like:
LogAndExecute("func-x", () => dm.Func-X(/*your args*/))
If you got problems with different different return types of your funcs, use generics
You can use simple delegate to accept the variable part as parameter (if no. of parameters to function call in single line are same)
public void Function_X(Func<object,..> func)
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
/**
* THIS SINGLE LINE IS THE VARIABLE PART
**/
// var output = dm.FUNC-X(...);
var output = func(...);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch (WebFaultException)
{
throw;
}
catch (OtherException ex)
{
if (Logger.IsErrorEnabled)
{
Logger.LogError("Exception in FUNC-X", ex);
}
throw new OtherException("Some Message");
}
catch (Exception ex)
{
if (IsErrorEnabled)
{
Logger("Exception in FUNC-X", ex);
}
throw new Exception("Generic Exception");
}
finally
{
if (IsDebugEnabled)
{
Logger("End FUNC-X");
}
}
}
You can create a common function that accepts a Func delegate:
static public TOutClass CommonFunc<TOutClass>(Func<Manager, TOutClass> func)
{
if (IsDebugEnabled)
{
Logger("Start DataLibrary: FUNC-X");
}
try
{
CheckInitSucceeded();
GetAuthenticationTokens();
var dm = new Manager();
TOutClass output = func(dm);
if (IsDebugEnabled)
{
var data = Serialize(output);
Logger(output);
}
return output;
}
catch
[...]
}
Your would write your functions as:
public OutClass FUNC-X(...)
{
return CommonFunc(dm=>dm.FUNC-X(...));
}

Categories

Resources