将许多方法重载转换为泛型方法,设计问题

时间:2010-11-24 15:46:28

标签: c# design-patterns generics

我正在尝试重构一些以前由其他人完成的代码,因为我发现它非常不实用 这是一个例子

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 个答案:

答案 0 :(得分:3)

消除交换机需求的一种方法是使用某种字典来保存委托,这些委托确定每种可能类型的构成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;
}

尽管如其他人所建议的那样,更改代码以使用Nullable类型会更好。

答案 1 :(得分:1)

你可以随时

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

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

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

之类的东西
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.

这会压缩您的类型验证和所有重载,并且它也不再需要通用方法。

答案 2 :(得分:0)

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

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

并可能使用此签名相应地调用它。 喜欢 的setParameter(PARAM,空) 的setParameter(PARAM,5)

答案 3 :(得分:0)

方法定义的“多重签名”方法非常好 - 它是赋予我们多态性的东西。就个人而言,我更愿意保留这种技术,而不是像你建议的那样重构。

然而,我 所做的是用“master”方法调用替换方法体的重复,然后通过调用参数来替换:

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)

很难用switch / if“删除”这个问题,最后有人必须这样做。 您可以选择覆盖/封装对象或类的null,但是您仍然需要检查每个概念中的null。

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

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类来封装你的null概念,nulls.Contains(parameterValue)检查列表中是否存在值。 你可以更进一步覆盖Contains以自己的方式检查,但你必须考虑你想花多少钱在这上面。