Передача типа столбца DataTable в универсальный метод <T> - PullRequest
1 голос
/ 25 августа 2011

У меня есть метод, объявленный как таковой

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

обычно я называю его так: var somnum = GetValidatedValue ("14");и ожидаем, что sumNum будет числом или если было передано недопустимое значение, равное «0»

, теперь моя проблема заключается в том, что мне нужно передать тип столбца базы данных как «T» в этот метод

что-то вроде:

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

это не скомпилирует

это в основном комбинация двух (2) методов, которые я где-то нашел (возможно, даже на этом сайте) и изменил, чтобы работать какмне нужно

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);
    }
}

может кто-нибудь пролить свет на то, что я делаю неправильно ...

Ответы [ 2 ]

0 голосов
/ 26 августа 2011

Обобщения действительно полезны только тогда, когда вы знаете, какой тип будет во время компиляции, и в этом случае вы можете вызвать свой метод следующим образом:

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

Тем не менее, мне кажется, что вы на самом деле не знаете тип во время компиляции, поэтому генерики будут только мешать. Попробуйте реализовать неуниверсальную версию вашего метода, например:

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);
    }
}

Таким образом, вы можете назвать это так:

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

(Хотя я должен признать, что кажется ненужным перерабатывать что-то в строку, а затем снова преобразовывать ее в исходный тип.)

Обновление

Теперь, когда я лучше понимаю, что вы пытаетесь сделать, описанный выше метод не сработает, потому что dr[col] не будет иметь любого типа, если он null, и будет иметь DbNull введите, если это DbNull. Если у вас нет другого способа определить, какой тип данных должен храниться в этом столбце, он просто не будет работать. Конечно, если вы сможете выяснить, какой тип данных должен быть там, получить значение по умолчанию будет очень просто:

public static object GetValidatedValue(string param, Type type)
{
    return param == null || param == DBNull.Value ? Activator.CreateInstance(type); 
}
0 голосов
/ 26 августа 2011

Как насчет метода KISS:

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];
}

Тогда вы просто называете это:

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