Sunday, March 29, 2009

Using Extension Methods to Verify the Method Calling

Using the extension method provided by C# 3.0 as the new feature, you can add the new methods for the compiled assembly to meet the need of extensible. In addition to this, extension method can also be effective to reduce duplicate code and improve the reusability of system if you are able to combine the generic and type inference. For example, the method like this:

public class CustomerDAL

{

    public IEnumerable<Customer> FindCustomers(string roleName)

    {

        return from customer

            in context.Customer

               where customer.RoleName.Equals(roleName)

               select customer;

    }

}

It will throw the NullReferenceException if you invoke it by this way as below when it returns null:

Customer customer = new CustomerDAL().FindCustomers(Role.Admin).First();

So we have to verify the result. If it is null, the custom exception should be thrown:

public IEnumerable<Customer> FindCustomers(string roleName)

{

    IEnumerable<Customer> customers = from customer

            in context.Customer

            where customer.RoleName.Equals(roleName)

            select customer;

    if (customers == null)

    {

        throw new MyException(“Cann’t find the customers.”);

    }

    return customers;

}

 

The logic of verification implemetation will spread through the everywhere in the system if there are too many methods which need to be verified. It is difficult to reuse these code, and it is bad smell absolutely.

Craig Andera post the blog to solve this problem. He wrote:
A NullReferenceException would be thrown, but we wanted something more specific. So we came up with this:

public static T OrThrow<T>(this T obj, Exception e) {

    if (obj == null) {

        throw e;

    }

    return obj;

}

 

Using the OrThrow() method, the invoking way might be changed like this:

Customer customer = new CustomerDAL().

    FindCustomers(Role.Admin).OrThrow

    (new MyException(“Can’t find Customer”)).First();

 

Craig continues to say:
the OrThrow extension method is generic on the type it’s invoked on, and it returns that type, so you can insert it into a chained expression and you don’t lose any intellisense. And because of type inference, you don’t actually have to specify the type, which cleans up the expression a bit.

That is, OrThrow() method can be applied to any type. Following this idea, we can create an instance as default value to avoid to throw the NullReferenceException using the extension method:

public static T Instance<T>(this T obj) where T:new()

{

    if (obj == null)

    {

        obj = new T();

    }

    return obj;

}

 

Due to type parameter T need to create an instance, we must add the constraint with new(). So that we can’t use the Instance<T> extension method for abstract type or interface type such as IEnumerable. But it is effective to method like this:

public class ListObject

{

    public List<string> Foo()

    {

        return null;

    }

}

 

Through by using Instance() method, we can invoke the related properties and methods of List instance safely. For example, we can use the Count property as below:

Console.WriteLine(new ListObject().Foo().Instance().Count);

No comments: