по умолчанию (T) для отраженного типа - PullRequest
4 голосов
/ 22 сентября 2011

Просматривая другие ответы, я нашел следующий метод расширения, который работает с удовольствием:

public static T Convert<T>( this string input )
{
    var converter = TypeDescriptor.GetConverter( typeof( T ) );
    if ( converter != null )
    {
        try
        {
            T result = (T) converter.ConvertFromString( input );
            return result;
        }
        catch
        {
            return default( T );
        }
    }
    return default( T );
}

И я могу использовать это как:

string s = "2011-09-21 17:45";
DateTime result = s.ConvertTo( typeof( DateTime ) );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

Отлично! Работает отлично. Теперь я хотел бы сделать что-то подобное с отраженным типом. У меня есть:

public static dynamic ConvertTo( this string input, Type type )
{
    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            dynamic result = converter.ConvertFromString( input );
            return ( result );
        }
        catch
        {
            return default( type );  // bogus
        }
    }

    return default( type );  // bogus
}

И я бы хотел использовать это так:

Type someType;  // will be DateTime, int, etc., but not known until runtime
DateTime result = s.ConvertTo( sometype );
if ( result == DateTime.MinValue )
    doSomethingWithTheBadData();

Конечно, компилятор возражает против «фиктивных» строк в методе ConvertTo . Что мне нужно (хорошо, не обязательно нужно , но это было бы неплохо), это способ получить тот же результат, что и в первом примере, чтобы в случае неудачного преобразования что-то, что можно было бы назначить к отраженному объекту возвращается и может быть распознан так же, как и в первом примере.

Edit:

Чем я закончил:

public static dynamic ConvertTo( this string input, Type type, out bool success )
{
    dynamic result;

    var converter = TypeDescriptor.GetConverter( type );
    if ( converter != null )
    {
        try
        {
            result = converter.ConvertFromString( input );
            success = true;
            return result;
        }
        catch { /* swallow the exception */ }
    }

    result = type.IsValueType ? Activator.CreateInstance( type ) : null;
    success = false;

    return result;
}

и используется:

bool success;
string val = "2011-09-21 17:25";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( success )
    doSomethingGood();

val = "foo";
dateTime = val.ConvertTo( typeof( DateTime ), out success );
if ( !success )
    dealWithBadData();

Помня, что для демонстрации я жестко кодирую бит typeof () . В моем приложении все типы отражены.

Спасибо всем за быстрые ответы!

Ответы [ 3 ]

9 голосов
/ 22 сентября 2011

Вы можете использовать

//to get default(T) from an instance of Type
type.IsValueType ? Activator.CreateInstance(type) : null;

Это потому, что типы значений гарантированно имеют конструктор по умолчанию, а значение по умолчанию для ссылочного типа - null.

4 голосов
/ 22 сентября 2011

Если вы передаете тип, используя typeof(Type), то, очевидно, вы можете просто использовать первый метод. Предполагая, таким образом, что вы получаете тип с помощью рефлексии (что вы и называете), вы также можете использовать рефлексию для получения MethodInfo для вашей первой версии Convert(), а затем использовать MakeGenericMethod() для замены отраженный в нем тип:

MethodInfo m = typeof(MyConvertExtensions).GetMethod("Convert");
MethodInfo invocable = m.MakeGenericMethod(myReflectedType);
invocable.Invoke(null, new[] { myString });
2 голосов
/ 22 сентября 2011

Не проверено, но может быть что-то вроде этого?

public static dynamic ConvertTo(this string input, Type type)
{
    var converter = TypeDescriptor.GetConverter(type);
    if (converter != null)
    {
        try
        {
            return converter.ConvertFromString(input);
        }
        catch
        {
            // ignore
        }
    }

    if (type.IsValueType)
        return Activator.CreateInstance(type);

    return null;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...