Konwersja typu Generic z string

Mam klasę, której chcę użyć do przechowywania "właściwości" dla innej klasy. Te właściwości mają po prostu nazwę i wartość. Idealnie, chciałbym móc dodać wpisane właściwości, tak aby zwracana "wartość" była zawsze tego typu, jaki chcę.

Typ zawsze powinien być prymitywny. Ta klasa podklasuje klasę abstrakcyjną, która zasadniczo przechowuje nazwę i wartość jako łańcuch znaków. Chodzi o to, że ta podklasa doda trochę bezpieczeństwa do bazy klasy (a także oszczędzić mi na jakimś nawróceniu).

Więc stworzyłem klasę, która jest (mniej więcej) taka:

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

Więc pytanie brzmi:

Czy istnieje "ogólny" sposób na konwersję z łańcucha z powrotem do prymitywnego?

Wydaje mi się, że nie mogę znaleźć żadnego ogólnego interfejsu, który łączy konwersję w całej planszy (coś w rodzaju ITryParsable byłoby idealne!).

Author: CRABOLO, 2008-08-12

9 answers

Nie jestem pewien, czy dobrze zrozumiałem twoje intencje, ale zobaczmy, czy to pomoże.

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();}
    }
}
 313
Author: lubos hasko,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-09 14:52:52

Dla wielu typów (integer, double, DateTime itd.) istnieje statyczna metoda Parse. Można go wywołać za pomocą refleksji:

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

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}
 10
Author: dbkk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-07 18:18:36
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor jest klasą posiadającą metodę GetConvertor, która akceptuje obiekt Type, a następnie można wywołać metodę ConvertFrom, Aby przekonwertować value dla tego określonego obiektu.

 5
Author: Dinesh Rathee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-06 07:48:17

Możesz użyć konstrukcji, takiej jak klasa cech . W ten sposób, będziesz miał sparametryzowaną klasę pomocniczą, która wie, jak przekonwertować łańcuch znaków na wartość własnego typu. Wtedy twój getter może wyglądać tak:

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

Teraz muszę podkreślić, że moje doświadczenie z parametryzowanymi typami jest ograniczone do C++ i jego szablonów, ale wyobrażam sobie, że jest jakiś sposób, aby zrobić to samo za pomocą C# generics.

 3
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-08-12 09:51:42

Sprawdź statykę Nullable.GetUnderlyingType. - Jeżeli podstawowym typem jest null, to parametrem szablonu nie jest Nullable i możemy użyć tego typu bezpośrednio - Jeśli typ bazowy nie jest null, to Użyj tego typu w konwersji.

Wydaje mi się, że działa:

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");
}
 1
Author: Bob C,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-08-07 17:53:00
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

Używam konwersji przez obiekt. To jest trochę prostsze.

 0
Author: Mastahh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-05-23 11:03:11

Użyłem lobos answer i działa. Ale miałem problem z konwersją sobowtórów ze względu na ustawienia Kultury. Więc dodałem

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
 0
Author: anhoppe,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-06-03 07:53:13

Kolejna odmiana. Obsługuje Nullables, a także sytuacje, w których łańcuch jest null, A T jest nie nullable.

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
Author: Todd Menier,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-07 21:26:54