One of the common problems faced by programmers is the need to reduce redundant code. Typically this is in a form where we need specific code surrounded by a common code block. Probably the best known version of optimizing this type of code is the c# using statement for disposing of objects. Instead of having to write the following code everywhere we interact with a disposable object
try
{
var obj = new SomeDisposableObject();
//specific_code_block_here
}
finally
{
if (obj != null)
obj.Dispose();
}
we can simply write
using (var obj = new SomeDisposableObject())
{
//specific_code_block_here
}
This is a great time saver and yields cleaner code. However, what happens when we want to create our own implementation for this pattern, with, for example, enhanced logging. Obviously we are not going to write our own compiler statments.
For our example, we will assume we have a MVC codebase where there are a lot of control methods accepting AJAX calls and needing to respond with a standardized JSON response.
public JsonResult<List<CoreModels.User>> GetUsers()
{
var result = new JsonResult<List<CoreModels.User>>();
try
{
result.Data = CoreServices.Account.GetUsers(); //specific code here
}
catch (Exception ex)
{
result.AddError(ex);
}
return result;
}
While this code is rather straight forward, it gets very repetitive to do the try catch error handling for our many methods. Lets introduce our own re-usable method to allow us to do the same logic with all of our methods.
public JsonResult<List<CoreModels.User>> GetUsers()
{
return API.Execute<List<CoreModels.User>>(result =>
{
result.Data = CoreServices.Account.GetUsers(); //specific code here
});
}
As you can see our method consists nearly all specific code. Only the call to our new API.Execute method is redundant. You may be wondering how this logic is accomplished. The answer is the use of a delegate (which allows the passing in of the lambda expression (result =>
)).
The code for the Execute method is fairly straight-forward even if you don't fully understand delegates.
public delegate void JsonResultHandler<T>(JsonResult<T> Result) where T : new();
public static JsonResult<T> Execute<T>(JsonResultHandler<T> codeFunc) where T : new()
{
var result = new JsonResult<T>(); //instantiate our JsonResult object of the passed in type (T)
try
{
codeFunc(result); //execute our passed in code
}
catch (Exception ex)
{
result.AddError(ex);
}
return result; //return the result
}