简体   繁体   中英

Passing DataTable Column Type to generic method <T>

I have a method declared as such

public static T GetValidatedValue<T>(string param)
{
   do something here and return object of type T...;
}

usually I call it like this var somnum = GetValidatedValue("14"); and expect sumNum to be number or if an invalid value was passed to be "0"

my problem now is that I need to pass a datatabel column type as "T" into this method

something like :

dr[col] = GetValidatedValue <typeof(dr[col])>(dr[col].ToString());

this will not compile

it is basicaly a combination of two(2) methods that I have found somewhere(maybe even on this site) and modified to work as i needed

public static T GetValidatedValue<T>(string param)
{
    return TryParse<T>(param);
}

private static T TryParse<T>(string inValue)
{
    var converter = TypeDescriptor.GetConverter(typeof(T));

    try
    {
        return (T)converter.ConvertFromString(null, CultureInfo.InvariantCulture,     inValue);
    }
    catch
    {
        return default(T);
    }
}

can anyone shed some light on what I am doing wrong...

How about the KISS method:

static readonly Dictionary<Type, object> defaultMap = new Dictionary<Type, object>()
        {
            { typeof(DateTime), DateTime.MinValue },
            { typeof(Int32), 0},
            { typeof(String), ""}
            /* etc etc etc*/
        };

private static void SetDefault(Type type, ref object value)
{
    if(value == DBNull.Value || value == null)
        value = defaultMap[type];
}

Then you just call it:

SetDefault(col.DataType, ref dr[col]);

Generics are really only useful when you know what the type will be at compile time, in which case you can call your method like this:

GetValidatedValue<int>(dr[col].ToString());

However, it looks to me like you don't actually know the type at compile time, so generics would only get in the way. Try implementing a non-generic version of your method, like this:

public static object GetValidatedValue(string param, Type type)
{
    return TryParse(param, type);
}

private static object TryParse(string inValue, Type type)
{
    var converter = TypeDescriptor.GetConverter(type);

    try
    {
        return converter.ConvertFromString(null, CultureInfo.InvariantCulture, inValue);
    }
    catch
    {
        return default(T);
    }
}

That way you can call it like this:

GetValidatedValue<int>(dr[col].ToString(), dr[col].GetType());

(Although I must admit it seems like unnecessary overhead to turn something into a string and then convert it back to its original type again.)

Update

Now that I better understand what you're trying to do, the above method won't work because dr[col] will not have any type if it is null , and it will have the DbNull type if it is DbNull . Unless you have some other way to determine what type of data should be stored in that column, it's just not going to work. Of course, if you can figure out what data type should be there, getting the default value will be totally easy:

public static object GetValidatedValue(string param, Type type)
{
    return param == null || param == DBNull.Value ? Activator.CreateInstance(type); 
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM