代码之家  ›  专栏  ›  技术社区  ›  Daniel Perez

将大量方法重载转换为泛型方法,设计问题

  •  3
  • Daniel Perez  · 技术社区  · 14 年前

    我在这里尝试重构一些以前由其他人完成的代码,因为我发现这很不实际 这里有一个例子

    protected void SetParameterValue(SqlParameter parameter, string parameterValue, bool isNullable)
    {
         if ((null == parameterValue || parameterValue == NULL_STRING) && isNullable)
                parameter.Value = DBNull.Value;
         else   parameter.Value = parameterValue;
    }
    
    protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable)
    {
         if (parameterValue == NULL_INT && isNullable)
                parameter.Value = DBNull.Value;
         else   parameter.Value = parameterValue;
    }
    
    protected void SetParameterValue( SqlParameter parameter, Int64 parameterValue, bool isNullable)
    {
         if (parameterValue == NULL_LONG && isNullable)
                parameter.Value = DBNull.Value;
         else   parameter.Value = parameterValue;
    }
    

    像那些,还有很多。现在我需要创建一个接受新类型的(它还没有方法)并决定也许我可以清理一点,使它更好。 我的想法是创造

    protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue, bool isNullable)
    

    但是,我不知道什么是最好的方法,我可以在这个通用方法中封装什么,以及我需要在单独的方法中做什么。值得吗?或者“很多方法”的方法是好的?我能从普通的那一个得到什么?谢谢!

    5 回复  |  直到 14 年前
        1
  •  3
  •   Grant Crofton    14 年前

    消除开关需求的一种方法是使用某种字典来保存委托,这些委托决定了对于每种可能的类型,什么构成null。尽管我认为你必须坚持这个目标。所以你会有一本字典,把它设置成:

    private Dictionary<Type, Func<object, bool, bool>> _nullChecks = new Dictionary<Type, Func<object, bool, bool>>();
    
    private void SetupNullChecks(){
        _nullChecks.Add(typeof(string), (object parameterValue, bool isNullable) => { return (null == parameterValue || parameterValue.ToString() == NULL_STRING) && isNullable; });
        _nullChecks.Add(typeof(int), (object parameterValue, bool isNullable) => { return (int)parameterValue == NULL_INT && isNullable; });
        _nullChecks.Add(typeof(long), (object parameterValue, bool isNullable) => { return (long)parameterValue == NULL_LONG && isNullable; });
    }
    

    你的支票是这样的:

    public void SetParameterValue(SqlParameter parameter, object parameterValue, bool isNullable)
    {
        if (_nullChecks[parameterValue.GetType()].Invoke(parameterValue, isNullable))
            parameter.Value = DBNull.Value;
        else parameter.Value = parameterValue;
    }
    

    不过,正如其他人所建议的那样,将代码更改为使用可空类型会更好。

        2
  •  1
  •   kemiller2002    14 年前

    你总是可以的

    Protected void SetParameterValue(SqlParameter parameter, 
     object parameterValue, bool isNullable)....
    

    parameter.Value 获取一个对象,因此减去每种类型的验证,您不需要将它们分开。

    您可以创建一个validate参数方法,该方法反映并提取参数的类型类型,并检查是否针对该类型设置了空值。 有点像

    bool IsNull (object value){
       if (value is int){
         check int..
       }
    }
    //this is a quick and dirty example, there are more elegant ways to handle it.
    

    这会压缩类型验证和所有重载,并且也不需要泛型方法。

        3
  •  0
  •   Eight-Bit Guru    14 年前

    方法定义的“多重签名”方法非常好——正是它给了我们多态性。就我个人而言,我宁愿保留这种技术,而不是像你建议的那样重构。

    但是,我 do是用对“master”方法的调用替换除one之外的所有方法体的重复,从而强制转换参数:

    protected void SetParameterValue(SqlParameter parameter, int parameterValue, bool isNullable)
    {
      SetParameterValue(parameter, (Int64)parameterValue, isNullable);
    }
    protected void SetParameterValue(SqlParameter parameter, Int64 parameterValue, bool isNullable)
    {
      if (parameterValue == NULL_INT && isNullable)
        parameter.Value = DBNull.Value;
      else
        parameter.Value = parameterValue;
    }
    

    前提是 parameterValue 当然,不需要太多麻烦就可以重播。

        4
  •  0
  •   Eugeniu Torica    14 年前

    我认为可以使用可空类型,而不是bool isNullable。

    protected void SetParameterValue<T>(SqlParameter parameter, T parameterValue)
    {
    if (parameterValue == null)
      parameter.Value = DBNull.Value;
    else
      parameter.Value = parameterValue;
    }
    

    可能会用这个签名来称呼它。 就像 SetParameter(param,空) 设置参数(参数,5)

        5
  •  0
  •   Vitor Navarro    14 年前

    用switch/if语句很难“移除”问题,如果最后有人不得不这么做。 您可以选择重写/封装对象或类的空值,但仍然需要检查每个概念中的空值。

    我不知道这是否会让事情变得更好,但是您可以首先通过创建前面所说的方法来隔离重复,或者只隔离空值检查。最后一个是我所做的:

    protected void SetParameterValue(SqlParameter parameter,object parameterValue){
        if(IsParameterNull(parameterValue) && parameter.IsNullable){
            parameter.Value = DBNull.Value;
        }
        else{
            parameter.Value = parameterValue;
        }
    }
    
    List<NULLTYPE> nulls = new List<NULLTYPE>(){new NULLTYPE(NULL_INT), new NULLTYPE(NULL_LONG), new NULLTYPE(null)}
    protected bool IsParameterNull(object parameterValue){
        if(nulls.Contains(parameterValue)) return true;
        else return false;
    }
    

    这里的工作是创建一个 NULLTYPE 类,该类封装了空的概念,并且 nulls.Contains(parameterValue) 检查该值是否存在于列表中。 你可以更进一步 Contains 去检查一下你自己的方法,但是你得想想你想在这上面花多少钱。