views:

111

answers:

4

Is there a pattern that I could apply to refactor this code? The only difference between the two methods is that that one method takes an extra parameter and passes it to the delegate?

I found out that delegates cannot take overloaded method signatures. How could I add one more level of indirection? :)

public static void ProcessFolder(
    ProcessFolderDelegate processFolderDelegate
)
{
    using (var esb = ExchangeService.GetExchangeServiceBinding())
    {
     var contactFolder = FolderService.GetPublicFolder(esb,  
         Properties.Settings.Default.ExchangePublicFolderName);
     processFolderDelegate(esb, contactFolder);
    }
}

public static void ProcessContact(  
    ProcessContactDelegate processContactDelegate,  
    Contact contact  //extra param
)
{
    using (var esb = ExchangeService.GetExchangeServiceBinding())
    {
     var contactFolder = FolderService.GetPublicFolder(esb,  
         Properties.Settings.Default.ExchangePublicFolderName);
     processContactDelegate(esb, contactFolder, contact); //extra param
    }
}
+1  A: 

No, the code you posted is actually a very terse method of applying this patter. You're not going to find a terser way unless there is some way of abstracting the type of method being called, or by removing all type safety, which I would not recommend

LorenVS
I agree. The replication in the two methods seems like a code smell, but i wouldn't worry about it with methods that small.
Jamie Penney
A: 

You could use anonymous methods or lambdas like this:

delegate void ProcessDelegate<T>(T param);
.
.
public static void Process<T>(ProcessDelegate<T> processDelegate)
{
    using (var esb = ExchangeService.GetExchangeServiceBinding())
    {
        var contactFolder = FolderService.GetPublicFolder(esb,  
            Properties.Settings.Default.ExchangePublicFolderName);
        processDelegate(contactFolder);
    }
}

and then call the method like this

Process(contactFolder => MyMethod(esb, contactFolder));
Process(contactFolder => MyMethod(esb, contactFolder, contact));

Where MyMethod is the actual method you're calling, so you contain it within your lambda expression rather than a delegate. Think something like that may work?

Charlie
The parameter 'ProcessDelegate' has an error: Using the generic type 'ProcessDelegate<T>' requires '1' type arguments
Even Mien
Sorry, fixed my answer, forgot to put the generic type parameter in the method
Charlie
+2  A: 
    public delegate void Action(TYPE_OF_ESB esb, TYPE_OF_CONTACT_FOLDER contact folder);
    private static void Process(Action action)
    {
        using (var esb = ExchangeService.GetExchangeServiceBinding())
        {
            var contactFolder = FolderService.GetPublicFolder(esb, Properties.Settings.Default.ExchangePublicFolderName);
            action(esb, contactfolder);
        }
    }

Process((esb, contactfolder)=>processFolderDelegate(esb, contactFolder));
Process((esb, contactfolder)=>processContactDelegate(esb, contactFolder, contact));
Jacob Seleznev
+1  A: 
public static void ProcessFolder(ProcessFolderDelegate del)
{
    Process((b, f) => del(b, f));
}

public static void ProcessContact(ProcessContactDelegate del, Contact contact)
{
    Process((b, f) => del(b, f, contact));
}

private static void Process(
    Action<ExchangeServiceBinding, ContactsFolderType> action)
{
    // i've guessed that esb is of type ExchangeServiceBinding
    // and that contactFolder is of type ContactsFolderType
    // if that's not the case then change the type parameters
    // of the Action delegate in the method signature above

    using (var esb = ExchangeService.GetExchangeServiceBinding())
    {
        var contactFolder = FolderService.GetPublicFolder(
            esb, Properties.Settings.Default.ExchangePublicFolderName);
        action(esb, contactFolder);
    }
}
LukeH