Click here to Skip to main content
15,890,438 members
Articles / Programming Languages / C#

ReSharper Hidden Features – Generate Delegating Members

Rate me:
Please Sign up or sign in to vote.
5.00/5 (2 votes)
16 Aug 2012CPOL3 min read 12.9K   5  
ReSharper hidden features – Generate delegating members

A frequently-used design pattern is the Decorator. This is also known as a mixin (or they might not be the very same thing but certainly they are related).

Typically, you might need to create a class that implements a certain interface and uses another class that implements that exact interface but you need to provide some additional feature(s). An example would be a class that adds transactional behavior to an existing data-access class (a naive example):

C#
public interface IDataAccess
{
    void AddCustomerInvoice(Invoice invoice, User user);
}

public class DataAccess : IDataAccess
{
    public void AddCustomerInvoice(Invoice invoice, User user)
    {
        InsertInvoice(invoice, user);
        UpdateCustomerDebt(user, invoice.Total);
    }

    // ... the rest of the implementation
}

public class TransactionalDataAccess : IDataAccess
{
    private readonly IDataAccess _dataAccess;

    public TransactionalDataAccess(IDataAccess dataAccess)
    {
        if (dataAccess == null)
        {
            throw new ArgumentNullException();
        }
        _dataAccess = dataAccess;
    }

    public void AddCustomerInvoice(Invoice invoice, User user)
    {
         using(var tx = new TransactionScope())
         {
             _dataAccess.AddCustomerInvoice(invoice, user);
             tx.Complete();
         }
    }

    // ... the rest of the implementation
}

Another type of example would be the Adapter design pattern. An example would be providing access to a (static) class (that may be out of your control) in a mock-able manner. That is, implement another class, non-static, which implements a defined interface and eases unit-testing:

C#
public class StorageManager
{
    public void StoreData(string key, byte[] data)
    {
         if (string.IsNullOrWhiteSpace(key))
         {
              throw new ArgumentNullException("key");
         }
         if (data == null)
         {
             throw new ArgumentNullException("data");
         }
         System.IO.File.WriteAllBytes(key + ".bin", data);
    }
}

This class, as you can see, uses the static File class in the BCL of .NET Framework. If I need to unit-test the StoreData method in a way to assert that the data is actually written to the file (and maybe test the file is named as the key and the binary data and only the binary data is placed in that file, etc.), then I can’t do it. Well, you might get away with TypeMock Isolator (expensive piece of… software) or Moles/Pex, but it’s just not right™.

So we define an interface...

C#
public interface IFileAccess
{
    void WriteAllBytes(string filePath, byte[] binaryContent);
}

...and then we write an implementation for this class:

C#
public class FileAccessAdapter : IFileAccess
{
    public void WriteAllBytes(string filePath, byte[] binaryContent)
    {
        System.IO.File.WriteAllBytes(filePath, binaryContent);
    }
}

Finally, we update the StorageManager class:

C#
public class StorageManager
{
    private readonly IFileAccess _fileAccess;

    public StorageManager(IFileAccess fileAccess)
    {
         if (fileAccess == null)
         {
             throw new ArgumentNullException("fileAccess");
         }
         _fileAccess = fileAccess;
    }

    public void StoreData(string key, byte[] data)
    {
         if (string.IsNullOrWhiteSpace(key))
         {
              throw new ArgumentNullException("key");
         }
         if (data == null)
         {
             throw new ArgumentNullException("data");
         }
         _fileAccess.WriteAllBytes(key + ".bin", data);
    }
}

Now we can unit test the StorageManager class by providing a mock of the IFileAccess interface.

Having finished the introduction, let’s get to business. The nice thing is that using these patterns, you have a more loosely-coupled code and you can unit test it. The not-so-nice thing is that you need to write a lot of repetitive code that’s really boring. I mean usually the interfaces won’t have 1-2 methods like my examples above but sometimes tens or even a hundred (yes, unfortunately, some people haven’t heard of ISP – Interface Segregation Principle).

Today, as I was creating such an adapter for a static class to which I don’t have much control, I thought: maybe ReSharper can help me… I looked in the implement interface dialog box, but no help. Then I turned to Google and as usual in the past few years, one of the best pieces of information came from Stackoverflow: How to (visual studio 2008 / Resharper) refactor / automate mixin pattern.

Trying to implement the adapter pattern, I failed since ReSharper does not support this scenario directly but being intrigued, I tried to create a decorator (the first scenario presented above). However, let’s resume the first example. At first, I wrote the class definition and the constructor for the TransactionalDataAccess class:

C#
public class TransactionalDataAccess : IDataAccess
{
    private readonly IDataAccess _dataAccess;

    public TransactionalDataAccess(IDataAccess dataAccess)
    {
        if (dataAccess == null)
        {
            throw new ArgumentNullException();
        }
        _dataAccess = dataAccess;
    }
}

Then, I pressed ALT-INSERT inside the block of code of the class:

Image 1

I selected Delegating members and then in the following dialog box:

Image 2

I selected all the interface’s members (in this simple example, there was only one but in production, I selected around 50 members). Finally, the code generated was like this:

C#
public class TransactionalDataAccess : IDataAccess
{
    private readonly IDataAccess _dataAccess;

    public TransactionalDataAccess(IDataAccess dataAccess)
    {
        if (dataAccess == null)
        {
            throw new ArgumentNullException();
        }
        _dataAccess = dataAccess;
    }

    public void AddCustomerInvoice(Invoice invoice, User user)
    {
        _dataAccess.AddCustomerInvoice(invoice, user);
    }
}

I just added the transaction wrapper:

C#
public class TransactionalDataAccess : IDataAccess
{
    private readonly IDataAccess _dataAccess;

    public TransactionalDataAccess(IDataAccess dataAccess)
    {
        if (dataAccess == null)
        {
            throw new ArgumentNullException();
        }
        _dataAccess = dataAccess;
    }

    public void AddCustomerInvoice(Invoice invoice, User user)
    {
        using (var tx = new TransactionScope())
        {
            _dataAccess.AddCustomerInvoice(invoice, user);
            tx.Complete();
        }
    }
}

… and I was done with it. For the adapter class, all you need is to extract the interface from the static class (you can view the metadata using Visual Studio and copy/paste it). Then create the adapter class, create a constructor with (at least) one parameter of the interface type, generate the delegating members just like above, modify or delete the constructor and the private field and replace (CTRL-H) all the occurrences of the private field with a call to the static class being adapted.

… That’s all folks!

This article was originally posted at http://blog.andrei.rinea.ro?p=197

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


Written By
Software Developer (Senior) IBM, Business Analytics
Romania Romania
This member has not yet provided a Biography. Assume it's interesting and varied, and probably something to do with programming.

Comments and Discussions

 
-- There are no messages in this forum --