通用功能<>作为基本方法的参数

时间:2010-06-16 15:20:14

标签: c# generics

我可能会失去情节,但我希望有人可以指出我正确的方向。

我想做什么?

我正在尝试编写一些基本方法,这些方法采用Func<>和Action,以便这些方法处理所有异常处理等,因此它不会在所有地方重复,但允许派生类指定它想要执行的操作。

到目前为止,这是基类。

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

我想在派生类中以下列方式执行Action(这似乎有效):

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

我想在派生类中以类似的方式执行一个Func但是对于我的生活,我似乎无法锻炼在基类中放置什么。

我希望能够以下列方式调用它(如果可能):

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

我是在想太疯狂还是这可能?提前感谢所有的帮助。

4 个答案:

答案 0 :(得分:4)

首先,你在这里做的异常可能是一个坏主意。所有例外的一般情况都不是你想要的。

但至于你正在做什么,你已经用Action解决了问题。为方便起见,您只需要调用Func版本的Action进行优化:

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

没有必要提供一种传递参数的方法,因为闭包已经解决了这个问题:

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

注意我是如何将方法设置为静态的,因为看起来ExecAction也可能是静态的,因为它不引用任何实例成员。如果方法是静态的,也许将它们移到单独的static类中会更清楚。

答案 1 :(得分:3)

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

顺便说一下,你的异常处理看起来有点狡猾:首先,抓住Exception本身并不是一种好习惯。请考虑捕获更具体的异常。其次,你在catch块中抛出一个新的异常,这意味着你从原始异常中丢失了堆栈跟踪等。您应该使用throw;代替重新抛出原始异常。 (这假设你的catch块正在做一些有用的工作。如果你所做的只是捕捉和投掷,那么就完全抛弃try...catch块。)

答案 2 :(得分:1)

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

然后你这样称呼它:

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

答案 3 :(得分:0)

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