Методы рефакторинга, вызывающие delgates с разными сигнатурами параметров - PullRequest
1 голос
/ 21 августа 2009

Есть ли шаблон, который я мог бы применить для рефакторинга этого кода? Единственное различие между этими двумя методами состоит в том, что этот метод принимает дополнительный параметр и передает его делегату?

Я обнаружил, что делегаты не могут принимать перегруженные сигнатуры методов. Как я могу добавить еще один уровень косвенности? :)

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
    }
}

Ответы [ 4 ]

3 голосов
/ 21 августа 2009
    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));
1 голос
/ 21 августа 2009
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);
    }
}
1 голос
/ 21 августа 2009

Нет, код, который вы разместили, на самом деле является очень кратким методом применения этого паттерна. Вы не найдете более краткого пути, если нет какого-либо способа абстрагирования типа вызываемого метода или удаления безопасности всех типов, что я бы не рекомендовал

0 голосов
/ 21 августа 2009

Вы можете использовать анонимные методы или лямбды, как это:

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);
    }
}

, а затем вызвать метод, подобный этому

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

Где MyMethod - фактический метод, который вы вызываете, поэтому вы содержите его в своем лямбда-выражении, а не в делегате. Думаешь, что-то подобное может сработать?

...