Преобразование общего типа из строки

c# generics primitive type-safety

110239 просмотра

10 ответа

У меня есть класс, который я хочу использовать для хранения «свойств» для другого класса. Эти свойства просто имеют имя и значение. В идеале я хотел бы иметь возможность добавлять типизированные свойства, чтобы возвращаемое «значение» всегда имело тот тип, который я хочу.

Тип всегда должен быть примитивным. Этот класс подклассов абстрактный класс, который в основном хранит имя и значение в виде строки. Идея состоит в том, что этот подкласс добавит некоторую безопасность типов к базовому классу (а также сэкономит мне на некотором преобразовании).

Итак, я создал класс, который (примерно) это:

public class TypedProperty<DataType> : Property
{
    public DataType TypedValue
    {
        get { // Having problems here! }
        set { base.Value = value.ToString();}
    }
}

Итак, вопрос:

Есть ли «общий» способ преобразования строки обратно в примитив?

Я не могу найти какой-либо универсальный интерфейс, который связывает преобразование по всем направлениям (что-то вроде ITryParsable было бы идеально!).

Автор: Rob Cooper Источник Размещён: 17.05.2019 02:47

Ответы (10)


334 плюса

Решение

Я не уверен, правильно ли я понял ваши намерения, но давайте посмотрим, поможет ли это.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}
Автор: lubos hasko Размещён: 12.08.2008 09:24

67 плюса

Метод Любоса Хаско не подходит для Nullables. Метод ниже будет работать для обнуляемых. Я не придумал это, все же. Я нашел его через Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Кредит "Тунец Токсоз"

Использование в первую очередь:

TConverter.ChangeType<T>(StringValue);  

Класс ниже.

public static class TConverter
{
    public static T ChangeType<T>(object value)
    {
        return (T)ChangeType(typeof(T), value);
    }

    public static object ChangeType(Type t, object value)
    {
        TypeConverter tc = TypeDescriptor.GetConverter(t);
        return tc.ConvertFrom(value);
    }

    public static void RegisterTypeConverter<T, TC>() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}
Автор: Tim Coker Размещён: 02.12.2009 02:11

13 плюса

Для многих типов (целое, двойное, DateTime и т. Д.) Существует статический метод Parse. Вы можете вызвать его, используя отражение:

MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}
Автор: dbkk Размещён: 12.08.2008 09:32

6 плюса

TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptorэто класс, имеющий метод, GetConvertorкоторый принимает Typeобъект, а затем вы можете вызвать ConvertFromметод для преобразования valueуказанного объекта.

Автор: Dinesh Rathee Размещён: 09.07.2013 11:26

3 плюса

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

get { return StringConverter<DataType>.FromString(base.Value); }

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

Автор: Greg Hewgill Размещён: 12.08.2008 09:23

2 плюса

Проверьте статический Nullable.GetUnderlyingType. - Если базовый тип имеет значение NULL, то параметр шаблона не равен Nullable, и мы можем использовать этот тип напрямую. - Если базовый тип не равен NULL, тогда используйте базовый тип в преобразовании.

Кажется, работает на меня:

public object Get( string _toparse, Type _t )
{
    // Test for Nullable<T> and return the base type instead:
    Type undertype = Nullable.GetUnderlyingType(_t);
    Type basetype = undertype == null ? _t : undertype;
    return Convert.ChangeType(_toparse, basetype);
}

public T Get<T>(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get<int>("14");
    int? nx = Get<Nullable<int>>("14");
}
Автор: Bob C Размещён: 07.08.2015 05:53

0 плюса

public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

Я использую конвертирование через объект. Это немного проще.

Автор: Mastahh Размещён: 17.12.2010 02:51

0 плюса

Я использовал ответ Лобоса, и он работает. Но у меня была проблема с конвертацией двойников из-за настроек культуры. Итак, я добавил

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
Автор: anhoppe Размещён: 03.06.2015 07:53

0 плюса

Еще один вариант. Обрабатывает Nullables, а также ситуации, когда строка имеет значение NULL и T не имеет значения NULL.

public class TypedProperty<T> : Property where T : IConvertible
{
    public T TypedValue
    {
        get
        {
            if (base.Value == null) return default(T);
            var type = Nullable.GetUnderlyingType(typeof(T)) ?? typeof(T);
            return (T)Convert.ChangeType(base.Value, type);
        }
        set { base.Value = value.ToString(); }
    }
}
Автор: Todd Menier Размещён: 07.08.2017 09:26

0 плюса

Вдохновленные ответом Боба , эти расширения также поддерживают преобразование нулевого значения и все примитивное преобразование назад и четвертое.

public static class ConversionExtensions
{
        public static object Convert(this object value, Type t)
        {
            Type underlyingType = Nullable.GetUnderlyingType(t);

            if (underlyingType != null && value == null)
            {
                return null;
            }
            Type basetype = underlyingType == null ? t : underlyingType;
            return System.Convert.ChangeType(value, basetype);
        }

        public static T Convert<T>(this object value)
        {
            return (T)value.Convert(typeof(T));
        }
}

Примеры

            string stringValue = null;
            int? intResult = stringValue.Convert<int?>();

            int? intValue = null;
            var strResult = intValue.Convert<string>();
Автор: Ghominejad Размещён: 13.03.2019 08:00
Вопросы из категории :
32x32