3

好的,我有一些我不太喜欢的代码。鉴于我没有写它,只是继承了它,我突然想到我可以清理一下它。基本上,我们有一个与 NHibernate 保持一致的设置对象。我不会对实现细节感到厌烦,只是说它包含一个字典,其中包含我们保存在数据库中的实际值。

我们典型的属性实现如下所示:

public string MyDumbProperty
{
get { return GetStringValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

现在,从上面的实现中可能很明显,我们为我们返回的每种类型(字符串、整数、长整数、浮点数等)都有单独的 Getxxxx 方法,第二个参数是默认值。我想要的是能够执行以下操作:

public string MyDumbProperty
{
get { return GetValue("MyDumbProperty", string.Empty); }
set { SetValue("MyDumbProperty", value);}
}

我有几个原因想要这样做。最大的问题是我个人不喜欢根据它们采用的参数类型命名的方法。第二个是我想为这个废话制作一个更清晰的模板。然后我可以只填写属性的名称和类型并完成(假设 resharper 可以为类型提供合理的默认值)。

我曾想过创建一个返回 T 的通用方法 GetValue,但我不确定我需要如何设置通用约束,所以这是可行的。从中返回的类型都是基本类型(字符串、整数等)。有几个返回数组,但我总是可以对它们做一些不同的事情。无论如何,这不是一个高优先级的问题,但每次看到它都会让我烦恼。我只是认为应该有更好的方法来做到这一点。

我想第一步就是重命名各种方法。由于它们在第二个参数中为默认值传递的类型有所不同,因此我至少可以将它们强制为相同的名称。但我能做得更好吗?如果我能摆脱每个方法中的多个重复代码位,这些重复代码仅在所使用的数据类型方面有所不同(所有数字类型中的 TryParse),那就太好了。

4

3 回答 3

3

我认为如果它的胆量不太复杂,您可能可以使用通用方法。例如,也许是这样的:

public T GetValue<T>(string name, T ifNull) where T : IConvertible
{
    string value = GetProperty(name);
    if (value == null)
        return ifNull;
    try
    {
        return (T)Convert.ChangeType(value, typeof(T));
    }
    catch
    {
        return ifNull;
    }
}

对于数组,您可能需要一个GetArrayValue执行不同操作的函数。

于 2012-06-06T20:20:07.407 回答
2

您可以使用default(T)来获取一个类型的默认值。

public T Get<T>(string propertyName)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    if(typeof(T) == typeof(string)) {
        return String.Empty;
    }
    return default(T);
}

更新

作为替代方案,您可以有两个重载,一个接受显式默认值。

public T Get<T>(string propertyName)
{
    return Get<T>(propertyName, default(T));
}

public T Get<T>(string propertyName, T defaultValue)
{
    object obj;
    if (propertyBag.TryGetValue(propertyName, out obj)) {
        return (T)obj;
    }
    return defaultValue;
}
于 2012-06-06T20:14:31.477 回答
1

.net 泛型的伟大之处在于,当它们表示哪些参数时,它们可以被隐式使用。不确定那句话的语法,但可以肯定的是,如果经常使用它是可能的..

例如对于 GetValue:

 public T GetValue<T>(string PropertyName, T DefaultValue)
 {

 }

 .... return GetValue("Prop1", 4); //T = int
 .....return GetValue("Prop2", string.Empty) //T= string
 //for nullable times, you can always include the generic parameter
 GetValue<int[]>("Prop3",null);
 //or by 'strongly typing' the null value:
 GetValue("Prop3", (int[])null); //for set this isn't a problem, since 'value' already is strongly typed

设置相同

public void SetValue<T>(string PropertyName, T Value)
{
}
于 2012-06-06T20:18:17.803 回答