0

我正在尝试使用泛型将一整套遗留方法隐藏在单个扩展方法后面。这些遗留方法都称为 GetValidXXX 并且具有类似的签名(是的,它们真的应该不在ref 。为了向后兼容,需要保留旧的 GetValidXXX。

    public static T GetAttributeValue<T>(this DbElement element, DbAttribute attribute, T defaultValue)
    {
        T result = default(T);
        if (typeof(T) == typeof(DbAttribute))
        {
            if (element.GetValidAttribute(attribute, ref result)) return result;
        }
        else if (typeof(T) == typeof(bool))
        {
            if (element.GetValidBool(attribute, ref result)) return result;
        }

        return defaultValue;
    }

这不会编译,因为结果与特定 GetValidXXX 签名中的类型不匹配(返回值为成功/失败)。

bool GetValidAttribute(DbAttribute attribute, ref DbAttribute result)
bool GetValidBool(DbAttribute attribute, ref bool result)
etc

我如何编写它来实现我的目标,即能够编写如下所示的代码:

string description = element.GetAttributeValue(DbAttributeInstance.DESC, "unset");
bool isWritable = !element.GetAttributeValue(DbAttributeInstance.READONLY, true);
4

2 回答 2

3

你不能使用T你的 ref 参数,因为编译器不能总是保证它是那些类型的。你必须做这样的事情:

public static T GetAttributeValue<T>(this DbElement element, DbAttribute attribute, T defaultValue)
{
    if (typeof(T) == typeof(DbAttribute))
    {
        var dbAttribute = default(DbAttribute);
        if (element.GetValidAttribute(attribute, ref dbAttribute)) return (T)(object)dbAttribute;
    }
    else if (typeof(T) == typeof(bool))
    {
        var boolResult = default(bool);
        if (element.GetValidBool(attribute, ref boolResult)) return (T)(object)boolResult;
    }

    return defaultValue;
}
于 2013-09-03T11:36:38.847 回答
1

Convert.ChangeType()在您的情况下可能有用。

可能的用法:

    public static T ConvertTypeOrGetDefault<T>(this object value, T defaultValue)
    {
        try
        {
            return (T)Convert.ChangeType(value, typeof(T));
        }
        catch (Exception ex)
        {
            return default(T);
        }
    }

这取决于您愿意成为“hacky”的程度。您还可以考虑重构,这样您就不必隐藏遗留方法。

于 2013-09-03T11:48:04.867 回答