Типовое преобразование типов из строки

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

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

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

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

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

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

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

12.08.2008 09:13:23
Мне было бы интересно увидеть пример вашего конкретного класса, даже просто фрагмент. :)
Jon Limjap 12.08.2008 09:54:03
Можете ли вы опубликовать соответствующие части вашего базового класса?
JJS 11.07.2012 21:26:08
Интересно, кто-нибудь может получить ответы здесь, работая в .Net Standard 1.2: /
Dan Rayson 3.11.2018 15:21:02
11 ОТВЕТОВ
РЕШЕНИЕ

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

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();}
    }
}
369
9.09.2015 14:52:52
В течение нескольких дней мне было интересно, как десериализовать поток в общий тип. Спасибо :)
Trap 30.09.2008 22:13:09
Я согласен, хотя Convert.ChangeTypeэто не очень универсальное и расширяемое решение, оно работает для большинства основных типов. если нужно что-то лучшее, нет проблем, чтобы обернуть этот метод во что-то большее, как предложил Тим, или использовать другой метод преобразования.
lubos hasko 11.01.2010 15:11:52
Я определенно добавил бы, где T: IConvertible
MikeT 7.11.2013 10:45:40
Тип T не должен быть IConvertible, но тип base.Value должен.
chapluck 15.09.2015 13:52:57

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

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

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

3
12.08.2008 09:51:42
Универсальные версии не существуют в C #.
Shimmy 10.07.2015 00:45:17

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

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

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}
13
7.02.2016 18:18:36

Метод Любоса Хаско не подходит для 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)));
    }
}
72
7.02.2016 18:18:20
я бы добавил опции конвертации в Fallback для структур Enums и Other Complex, но хороший вызов.
Tomer W 27.03.2012 14:10:56
Почему RegisterTypeConverter? Нужно ли регистрировать конвертеры заранее? (к сожалению, ссылка мертва, поэтому я не смог ее прочитать)
Cohen 30.11.2012 09:40:45
Для нескольких конверсий вы, вероятно, должны создавать tc( TypeConverter) только один раз. TypeConverterмедленный, потому что он использует отражение для поиска TypeConverterAttribute. Если вы инициализируете одно приватное TypeConverterполе, вы сможете использовать его TypeConverterмного раз.
Kevin P. Rice 21.01.2013 08:44:04
Работает нормально, но если T является object, выдает исключение. Я смог обойти это, используя `if (typeof (T) .IsPrimitive) {return TConverter.ChangeType <T> (StringValue); } else {object o = (object) StringValue; Вернуться к; } `в качестве замены для примера использования TConverter.ChangeType<T>(StringValue)
Matt 24.02.2016 17:26:11
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

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

0
23.05.2011 11:03:11
спасибо, я должен преобразовать T в интерфейсе, и простой объект преобразования T работает правильно, легко и быстро, спасибо
LXG 10.02.2012 09:42:49
(INT) (объект) "54"; это СМЕРТЬ !, это не VB!
Tomer W 27.03.2012 14:08:23
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

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

8
6.10.2015 07:48:17
Я лично думаю, что этот интерфейс лучше для обработки преобразования вместо метода Convert.ChangeType, так как вам нужно реализовать интерфейс IConvertible во всех ваших классах.
Sauleil 29.11.2019 04:01:16

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

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
0
3.06.2015 07:53:13

Проверьте статический 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");
}
2
7.08.2015 17:53:00

Еще один вариант. Обрабатывает 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(); }
    }
}
0
7.08.2017 21:26:54

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

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>();
1
13.03.2019 08:00:42

Вы можете сделать это в одну строку, как показано ниже:

YourClass obj = (YourClass)Convert.ChangeType(YourValue, typeof(YourClass));

Удачного кодирования;)

0
6.03.2020 13:28:16
Когда вы поделились кодом в качестве ответа, пожалуйста, попробуйте объяснить это.
Yunus Temurlenk 6.03.2020 13:48:08