tags:

views:

90

answers:

4

I might be losing the plot, but I hope someone can point me in the right direction.

What am I trying to do?

I'm trying to write some base methods which take Func<> and Action so that these methods handle all of the exception handling etc. so its not repeated all over the place but allow the derived classes to specify what actions it wants to execute.

So far this is the base class.

public abstract class ServiceBase<T>
{
    protected T Settings { get; set; }

    protected ServiceBase(T setting)
    {
        Settings = setting;
    }

    public void ExecAction(Action action)
    {
        try
        {
            action();
        }
        catch (Exception exception)
        {
            throw new Exception(exception.Message);
        }
    }

    public TResult ExecFunc<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function)
    {
        try
        {
            /* what goes here?! */
        }
        catch (Exception exception)
        {
            throw new Exception(exception.Message);
        }
    }
}

I want to execute an Action in the following way in the derived class (this seems to work):

public void Delete(string application, string key)
{
  ExecAction(() => Settings.Delete(application, key));
}

And I want to execute a Func in a similar way in the derived class but for the life of me I can't seem to workout what to put in the base class.

I want to be able to call it in the following way (if possible):

public object Get(string application, string key, int? expiration)
{
  return ExecFunc(() => Settings.Get(application, key, expiration));
}

Am I thinking too crazy or is this possible? Thanks in advance for all the help.

A: 
public TResult ExecFunc<T1, T2, T3, TResult>(Func<T1, T2, T3, TResult> function, T1 t1Param, T2 t2Param, T3 t3Param)
{
    try
    {
        return function(t1Param, t2Param, t3Param);
    }
    catch (Exception exception)
    {
        throw new Exception(exception.Message);
    }
}

Then you call it like this:

public object Get(string application, string key, int? expiration)
{
    return ExecFunc(Settings.Get, application, key, expiration);
}
BFree
A: 
public object Get(string application, string key, int? expiration) 
{ 
    object result = null;
    ExecAction(() => result = Settings.Get(application, key, expiration)); 
    return result
}
Henrik
+1  A: 
public void Delete(string application, string key)
{
    ExecAction(() => Settings.Delete(application, key));
}

public object Get(string application, string key, int? expiration)
{
    return ExecFunc(() => Settings.Get(application, key, expiration));
}

// ...

public TResult ExecFunc<TResult>(Func<TResult> func)
{
    try
    {
        return func();
    }
    catch (Exception exception)
    {
        throw new Exception(exception.Message);
    }
}

By the way, your exception handling looks a bit dodgy: Firstly, it's not considered good practice to catch Exception itself. Consider catching more specific exceptions instead. Secondly, you're throwing a new exception in your catch block, which means that you're losing the stacktrace etc from the original exception. You should use throw; instead to rethrow the original exception. (This assumes that your catch block is doing some sort of useful work. If all you're doing is catching and throwing then just ditch the try...catch blocks altogether.)

LukeH
Thanks for the response; has worked a treat. I knew I'd missed something in my previous attempts before posting. I agree about the exception handling looking dodgy it was purely put in during the initial developement phase this will be sorted out :-)
WestDiscGolf
+2  A: 

Firstly, what you're doing with exceptions here is probably a bad idea. A general catch of all exceptions is hardly ever what you want.

But as for generally what you're doing, you already solved the problem with Action. For convenience you just need a refinement for Func that calls the Action version:

public static TResult ExecFunc<TResult>(Func<TResult> func)
{
    TResult result = default(TResult);
    ExecAction(() => result = func());
    return result;
}

There is no need to provide a way to pass arguments through, because closures already solve that problem:

var someData = "Hi!";
var result = ExecFunc(() => SomeOtherMethod(someData));
// the lambda can close over the local variables of the outer scope

Note how I've made the method static, because it looks like ExecAction could also be static, because it doesn't refer to any instance members. And if methods are static, maybe it would be clearer to move them into a separate static class.

Daniel Earwicker
Thanks for the response; +1 interesting re-usage of the ExecAction functionality :-) As for the exception handling, this will be fixed it was only added in for the intial dev phase. Its up next to be fixed.
WestDiscGolf
Cool - this is why it's good to make `ExecFunc` call `ExecAction`, so when you change the wrapping code you only have to do it once. :)
Daniel Earwicker