Tip de conversie generică FROM din șir

Am o clasă pe care vreau să o folosesc pentru a stoca "proprietăți" pentru o altă clasă. Aceste proprietăți au pur și simplu un nume și o valoare. În mod ideal, aș vrea să adaug proprietățile tipizate , astfel încât valoarea "returnată" să fie întotdeauna de tipul pe care vreau să fie.

Tipul ar trebui să fie întotdeauna primitiv. Această clasă subclasează o clasă abstractă care stochează în principiu numele și valoarea ca șir. Ideea fiind că această subclasă va adăuga o anumită siguranță de tip la clasa de bază (precum și salvarea mea pe o anumită conversie).

Deci, am creat o clasă care este (aproximativ) aceasta:

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

Deci, întrebarea este:

Există o modalitate "generică" de a converti dintr-un șir într-un primitiv?

Nu pot să găsesc nicio interfață generică care să lege conversia peste bord (ceva de genul ITryParsable ar fi fost ideal!).

0
fr hi bn
Aș fi interesat să văd un exemplu de clasă de beton, chiar și un fragment. :)
adăugat autor Jon Limjap, sursa
poți să trimiți părțile relevante din clasa de bază?
adăugat autor JJS, sursa

9 răspunsuri

Ați putea folosi o construcție, cum ar fi un clasă de trăsături . În acest fel, ați avea o clasă helper parametrizată care știe cum să convertească un șir la o valoare de tip propriu. Apoi, getterul dvs. ar putea arăta astfel:

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

Acum, trebuie să subliniez că experiența mea cu tipuri parametrizate este limitată la C ++ și la șabloanele sale, dar îmi imaginez că există o modalitate de a face același lucru folosind generice C #.

0
adăugat
Versiunile generice nu există în C #.
adăugat autor Shimmy, sursa

O altă variație. Manipulează Nullables, precum și situațiile în care șirul este nul și T este nu nullabil.

public class TypedProperty : 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
adăugat

Am folosit raspunsul lobos si functioneaza. Dar am avut o problemă cu conversia dublează din cauza setărilor culturale. Așa că am adăugat

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
0
adăugat

Nu sunt sigur dacă am înțeles corect intențiile voastre, dar să vedem dacă acest lucru vă ajută.

public class TypedProperty : Property where T : IConvertible
{
    public T TypedValue
    {
        get { return (T)Convert.ChangeType(base.Value, typeof(T)); }
        set { base.Value = value.ToString();}
    }
}
0
adăugat
Acest lucru funcționează numai dacă tipul dvs. implementează IConvertible
adăugat autor Kilhoffer, sursa
Mă întrebam de câteva zile cum să deserializăm un flux într-un tip generic. Mulțumiri :)
adăugat autor Trap, sursa
Aș adăuga cu siguranță unde T: IConvertible
adăugat autor MikeT, sursa
Sunt de acord, deși Convert.ChangeType nu este o soluție foarte universală și extensibilă, funcționează pentru majoritatea tipurilor de bază. dacă este nevoie de ceva mai bun, nu este nici o problemă să înfășurați această metodă în ceva mai mare, cum a sugerat Tim sau să utilizați o altă metodă de conversie diferită.
adăugat autor lubos hasko, sursa
Tipul T nu ar trebui să fie IConvertible, ci tipul de bază. Valoarea ar trebui să fie.
adăugat autor chapluck, sursa

Pentru multe tipuri (integer, double, DateTime etc.), există o metodă statică Parse. Puteți să o invocați folosind reflecția:

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

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}
0
adăugat

metoda lui lubos hasko eșuează pentru nullabile. Metoda de mai jos va funcționa pentru nullabile. Nu am venit cu asta. Am găsit-o prin Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Credit pentru "Ton Tokos"

Utilizare mai întâi:

TConverter.ChangeType(StringValue);  

Clasa este mai jos.

public static class TConverter
{
    public static T ChangeType(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() where TC : TypeConverter
    {

        TypeDescriptor.AddAttributes(typeof(T), new TypeConverterAttribute(typeof(TC)));
    }
}
0
adăugat
Funcționează bine, dar dacă T este un object , aruncă o excepție. Am reușit să rezolv această problemă folosind "if (typeof (T) .IsPrimitive) {retur TConverter.ChangeType (StringValue); } altceva {obiect o = (obiect) StringValue; intoarce-te; } ca înlocuitor pentru eșantionul de utilizare TConverter.ChangeType (StringValue)
adăugat autor Matt, sursa
De ce RegisterTypeConverter? Trebuie să înregistrăm convertoarele în prealabil? (din păcate, legătura este mortă, așa că nu am putut să citesc)
adăugat autor Cohen, sursa
Pentru mai multe conversii, ar trebui să creați probabil tc ( TypeConverter ) numai o singură dată. TypeConverter este lent deoarece folosește reflecția pentru a căuta TypeConverterAttribute . Dacă inițializați un singur câmp TypeConverter unic, atunci ar trebui să puteți reutiliza de mai multe ori codul TypeConverter .
adăugat autor Kevin P. Rice, sursa
i-ar adăuga o opțiuni de conversie Fallback pentru Enums și alte structuri complexe, dar un apel bun.
adăugat autor Tomer W, sursa
public class TypedProperty : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

Folosesc conversia printr-un obiect. E un pic mai simplu.

0
adăugat
(Int) (obiect) "54"; este o FATALITATE !, acest lucru nu este VB!
adăugat autor Tomer W, sursa
mulțumesc că trebuie să convertesc un T într-o interfață și obiectul simplu de conversie T funcționează corect, mulțumesc ușor și rapid
adăugat autor LXG, sursa
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor is class having method GetConvertor which accept a Type object and then you can call ConvertFrom method to convert the value for that specified object.

0
adăugat
Deja a răspuns corect?
adăugat autor nawfal, sursa

Verificați codul static Nullable.GetUnderlyingType . - Dacă tipul de bază este nul, atunci parametrul șablonului nu este Nullable și putem folosi acel tip direct - Dacă tipul de bază nu este nul, utilizați tipul de bază în conversie.

Pare să lucreze pentru mine:

public object Get( string _toparse, Type _t )
{
   //Test for Nullable 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(string _key)
{
    return (T)Get(_key, typeof(T));
}

public void test()
{
    int x = Get("14");
    int? nx = Get>("14");
}
0
adăugat