Bezdepbonusu7Программирование: статьи и ответы

Вопрос

Лучший способ избежать повторения кода с помощью Generics и Func в С#

Автор вопроса: user2418209Ответов: 1

Я хотел бы знать, как лучше всего избежать повторения некоторой повторяющейся структуры кода с помощью Generics Func или любым другим способом. В качестве практического примера давайте мне нужно вызвать 20 различных методов WCF, но я хотел бы иметь код для обработки исключений.

Допустим, это прокси wcf

 class ClassWithMethodsToCall // say wcf proxy
    {
        public Out1 GetOut1(In1 inParam) { return null; } // would have some spesific implementation
        public Out2 GetOut2(In2 inParam) { return null; }
        public Out3 GetOut3(In3 inParam) { return null; }
    }

class Out1 { }  // some specific data structure
class In1 { }   // some specific data structure

class Out2 { }  // some specific data structure
class In2 { }   // some specific data structure

class Out3 { }  // some specific data structure
class In3 { }   // some specific data structure

Я создал следующее, чтобы иметь одну обработку ошибок

class CallerHelperWithCommonExceptionHandler
    {
        public Tout Call<Tout, Tin>(Tin parameters, Func<Tin,Tout> wcfMethodToCall)
        {
            try
            {
                return wcfMethodToCall(parameters);
            }
            catch (Exception ex)
            {
                // do what ever
                throw;
            }
        }
    }

И я использую его:

var callerHelper = new CallerHelperWithCommonExceptionHandler();
            var theFunctionsToCall = new ClassWithMethodsToCall();

        var in1 = new In1(); // init as appropriate
        var ou1 = callerHelper.Call<Out1, In1>(in1, theFunctionsToCall.GetOut1);

        var in2 = new In2(); // init as appropriate
        var ou2 = callerHelper.Call<Out2, In2>(in2, theFunctionsToCall.GetOut2);

        // and so on

Есть ли лучший более элегантный способ? Альтернативы объектно-ориентированному подходу, шаблон проектирования шаблонов?

Спасибо, аль

  • Это вовсе не повторение. Ваш класс ClassWithMethodsToCall мне подходит. Ваш CallerHelperWithCommonExceptionHandler усугубляет ИМО. Sriram Sakthivel 19.02.2015
  • Согласен, выглядит гораздо хуже. BenjaminPaul 19.02.2015
  • То, что вы ищете, может быть Аспектно-ориентированным программированием, коротким АОП, вот пример ayende. com/blog/3474/logging-the-aop-way BoeseB 19.02.2015
  • Что ж, без CallerHelperWithCommonExceptionHandler мне приходится повторять try catch для каждого вызова метода ClassWithMethodsToCall . Если бы у меня было 20 методов, я бы повторил один и тот же блок кода обработки ошибок для каждого из них. user2418209 19.02.2015

genericscode-duplicationfunc

Ответы

Ответ 1 · рейтинг 4 · Matthew Watson

Похоже, вы добавляете код для реализации сквозной задачи в классе (например, регистрации исключений), поэтому вы можете использовать шаблон декоратора.

Например:

class Out1 { };  // some specific data structure
class In1 { }   // some specific data structure

class Out2 { }  // some specific data structure
class In2 { }   // some specific data structure

class Out3 { }  // some specific data structure
class In3 { }

internal interface IClassWithMethodsToCall
{
    Out1 GetOut1(In1 inParam);
    Out2 GetOut2(In2 inParam);
    Out3 GetOut3(In3 inParam);
}

class ClassWithMethodsToCallImpl: IClassWithMethodsToCall
{
    public Out1 GetOut1(In1 inParam) { return null; } // would have some spesific implementation
    public Out2 GetOut2(In2 inParam) { return null; }
    public Out3 GetOut3(In3 inParam) { return null; }
}

class ClassWithMethodsToCall: IClassWithMethodsToCall
{
    private readonly ClassWithMethodsToCallImpl _impl;

    public ClassWithMethodsToCall(ClassWithMethodsToCallImpl impl)
    {
        _impl = impl;
    }

    public Out1 GetOut1(In1 inParam)
    {
        return tryFunc(() => _impl.GetOut1(inParam));
    }

    public Out2 GetOut2(In2 inParam)
    {
        return tryFunc(() => _impl.GetOut2(inParam));
    }

    public Out3 GetOut3(In3 inParam)
    {
        return tryFunc(() => _impl.GetOut3(inParam));
    }

    private static T tryFunc<T>(Func<T> func)
    {
        try
        {
            return func();
        }

        catch (Exception exception)
        {
            // Do something with exception
            throw;
        }
    }
}

Клиентский код будет использовать только IClassWithMethodsToCall, и вы, вероятно, будете использовать фабричный метод где-нибудь, который создает ClassWithMethodsToCallImpl и использует его для создания ClassWithMethodsToCall и возвращает ClassWithMethodsToCall как IClassWithMethodsToCall.

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

Я заметил, что вы используете прокси-сервер WCF. Поскольку для этого используется MarshalByRefObject, вы можете использовать его для реализации АОП. Некоторая информация об этом есть в блоге здесь а>.

Перевод вопроса и ответов сообщества Stack Overflow, лицензия CC BY-SA. Оригинал на Stack Overflow.

Похожие материалы