代码之家  ›  专栏  ›  技术社区  ›  WestDiscGolf

泛型func<>作为基方法的参数

  •  0
  • WestDiscGolf  · 技术社区  · 14 年前

    我可能失去了计划,但我希望有人能给我指明正确的方向。

    我想做什么?

    我正在尝试编写一些采用func<gt;和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);
            }
        }
    }
    

    我希望在派生类中以以下方式执行操作(这似乎有效):

    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 回复  |  直到 14 年前
        1
  •  3
  •   LukeH    14 年前
    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 块,这意味着您将从原始异常中丢失stacktrace等。你应该使用 throw; 而是重新引发原始异常。(这假设 抓住 布洛克正在做一些有用的工作。如果你所做的只是接球和投掷,那就把球扔了。 try...catch 全部阻塞。)

        2
  •  4
  •   Daniel Earwicker    14 年前

    首先,除了例外,你在这里做的事情可能是个坏主意。对所有例外情况的一个普遍的捕捉几乎不是你想要的。

    但一般来说,你已经解决了这个问题 Action . 为了方便你只需要一个精致的 Func 那叫 行动 版本:

    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 班级。

        3
  •  1
  •   BFree    14 年前
    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);
    }
    
        4
  •  0
  •   Henrik    14 年前
    public object Get(string application, string key, int? expiration) 
    { 
        object result = null;
        ExecAction(() => result = Settings.Get(application, key, expiration)); 
        return result
    }