Thursday, September 4, 2014

Generic result class with C#

Generic result class with C#


Summary

In this post, I discuss a way to create a result class that can be used for method calls across multiple layers in your application. I discuss the need for such an approach and my take on the solution. I welcome recommendations to make this solution better.

Introduction

It has become the norm that when one starts creating a .net solution, one follows a layered approach. Following the standard n-layered architecture, one creates a number of class libraries to represent the layers. Often times, I have come across the problem of getting the results from the lowest layer to the topmost layer. So, for example, I write a method that gets data from the database and populate an object and I need to return this object to the UI, the norm is to create a method signature that returns the object type. An issue arise when errors happen, how do I get to send these errors to the upper layers?
The following sections look at a solution I came to like and have been using in most of my solutions. Let’s assume I am writing an application to read manage student details. I will define some methods to manage this data and describe a way to use a generic result class I can use in all my methods. I will also describe a caveat to this solution and a work around.

IStudentRepository


public interface IStudentRepository
{
long AddStudent(Student newStudent);
Student GetStudent(long studentId);
bool UpdateStudent(Student updatedStudent);
}
Note that all my methods return a different data type. How should I handle errors that occur when trying to access my persistence layer? The solution I use id to create a generic result class that has the capability to carry errors as well as my results and any other piece of information. I also use a couple of other classes to help manage this.

Generic result


[DataContract]
    public class Result
    {
        public Result()
        {
            IsValid = true;
            Errors = new List<Error>();
        }

        [DataMember]
        public T Value { get; set; }

        [DataMember]
        public bool IsValid { get; set; }


        [DataMember]
        public List<Error> Errors { get; set; }

        [DataMember]
        public List<string> InfoMessages { get; set; }
    }
[DataContract]
    public class Error
    {
        [DataMember]
        public string ErrorCode { get; set; }
        [DataMember]
        public string ErrorMessage { get; set; }
        [DataMember]
        public ErrorType Severity { get; set; }
    }
The DataContract attibutes have been added allow this to be serialized in WCF for example. Now using this class, here is how I define the same interface above
public interface IStudentRepository
{
Result<long> AddStudent(Student newStudent);
Result<Student> GetStudent(long studentId);
Result<bool> UpdateStudent(Student updatedStudent);
}

Using this approach, in my code I first check if the result is valid, if it is, I can access the strongly typed Value property to get the results and pontentially any InfoMessages I can use for notifications. If the result is invalid, I can access the list of errors to get more information on what went wrong.

Caveat L


With this solution, you will realize that it will not work when your result type is a string, a work around is to wrap your string value in an object

I hope you find this useful in your solutions too.



No comments:

Post a Comment