4

I'd like to know what is the best way to avoid repeating some recuring code structure by using Generics Func or any other way. As a practical example let's I need to call 20 different WCF methods but I would like to have on code to handle exception.

Let's say this is the wcf proxy

 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

I created the following to have the one single error handling

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

And I use it:

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

Is there a better more elegant way? Alternatives in object oriented way, Template Design Pattern?

Thanks, al

DrKoch
  • 9,556
  • 2
  • 34
  • 43
user2418209
  • 109
  • 8
  • 3
    This is not a repetition at all. Your class `ClassWithMethodsToCall` looks fine for me. Your `CallerHelperWithCommonExceptionHandler` makes it worse IMO. – Sriram Sakthivel Feb 19 '15 at 09:38
  • 1
    Agreed, looks much worse. – BenjaminPaul Feb 19 '15 at 09:39
  • 1
    What you are looking for could be Aspect Oriented Programming short AOP here is an example http://ayende.com/blog/3474/logging-the-aop-way – BoeseB Feb 19 '15 at 09:51
  • Well, without CallerHelperWithCommonExceptionHandler I have to repeat the try catch for every metod call of ClassWithMethodsToCall . If I have 20 methods than I would repeat the same error handling code block for each of them. – user2418209 Feb 19 '15 at 10:39

1 Answers1

4

It looks like you are adding code to implement a cross-cutting concern to a class (e.g. logging exceptions), so you might want to use the decorator pattern.

For example:

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

Client code would only use an IClassWithMethodsToCall, and you would probably use a factory method somewhere which creates a ClassWithMethodsToCallImpl and uses it to create a ClassWithMethodsToCall and returns the ClassWithMethodsToCall as an IClassWithMethodsToCall.

Alternatively (and probably better) would be to use Aspect-oriented programming. That requires more investment and probably the use of third party libraries to support it, but it's probably the way to go in the long term.

I notice that you are using a WCF proxy. Because that uses MarshalByRefObject it may be possible for you to leverage that to implement AOP. There's some information about it in a blog here.

Matthew Watson
  • 104,400
  • 10
  • 158
  • 276
  • Matthew, your example makes sense. While the AOP as I understand is more specific to exceptions, logging, ..., common operations. I am looking to something that would fit any common code block, for example this http://stackoverflow.com/questions/13159326/implementing-retry-logic-for-deadlock-exceptions "1.Solution:" seems similar to mine What do you think? – user2418209 Feb 19 '15 at 11:21
  • @user2418209 Yes, that's essentially the same as the `private static T tryFunc(Func func)` I showed - you can use that approach to implement retry logic by putting the retries inside `tryFunc()` – Matthew Watson Feb 19 '15 at 11:26
  • @user2418209 AOP is not just limited to logging/exception handling it is possible to implement for example caching, transaction handling and more. Just everything that needs to intercept calls to the objects methods. so retry logic would also be possible in AOP – BoeseB Feb 20 '15 at 07:28