Domanda

Ho una classe che voglio utilizzare per memorizzare "proprietà" per un'altra classe.Queste proprietà hanno semplicemente un nome e un valore.Idealmente, quello che vorrei è poter aggiungere digitato proprietà, in modo che il "valore" restituito sia sempre del tipo che voglio che sia.

Il tipo dovrebbe essere sempre primitivo.Questa classe sottoclasse una classe astratta che sostanzialmente memorizza il nome e il valore come stringa.L'idea è che questa sottoclasse aggiungerà un po' di sicurezza sui tipi alla classe base (oltre a risparmiarmi alcune conversioni).

Quindi, ho creato una classe che è (approssimativamente) questa:

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

Quindi la domanda è:

Esiste un modo "generico" per riconvertire da stringa a primitiva?

Non riesco a trovare alcuna interfaccia generica che colleghi la conversione su tutta la linea (qualcosa come ITryParsable sarebbe stato l'ideale!).

È stato utile?

Soluzione

Non sono sicuro di aver capito correttamente le tue intenzioni, ma vediamo se questo aiuta.

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();}
    }
}

Altri suggerimenti

Il metodo di lubos hasko fallisce per i nullable.Il metodo seguente funzionerà per i nullable.Non l'ho inventato io, però.L'ho trovato tramite Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Ringraziamo "Tonno Toksoz"

Primo utilizzo:

TConverter.ChangeType<T>(StringValue);  

La classe è sotto.

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)));
    }
}

Per molti tipi (intero, double, DateTime ecc.), esiste un metodo Parse statico.Puoi invocarlo usando la riflessione:

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

if (m != null)
{
    return m.Invoke(null, new object[] { base.Value });
}
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor è una classe che ha un metodo GetConvertor che accettano a Type oggetto e quindi puoi chiamare ConvertFrom metodo per convertire il file value per quell'oggetto specificato.

Potresti eventualmente usare un costrutto come a classe dei tratti.In questo modo avresti una classe helper parametrizzata che sa come convertire una stringa in un valore del suo stesso tipo.Quindi il tuo getter potrebbe assomigliare a questo:

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

Ora, devo sottolineare che la mia esperienza con i tipi parametrizzati è limitata al C++ e ai relativi modelli, ma immagino che esista un modo per fare lo stesso genere di cose utilizzando i generici C#.

Controlla l'elettricità statica Nullable.GetUnderlyingType.-Se il tipo sottostante è null, il parametro del modello non lo è Nullable, e possiamo usare direttamente quel tipo: se il tipo sottostante non è nullo, quindi utilizzare il tipo sottostante nella conversione.

Sembra funzionare per me:

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");
}
public class TypedProperty<T> : Property
{
    public T TypedValue
    {
        get { return (T)(object)base.Value; }
        set { base.Value = value.ToString();}
    }
}

Utilizzo la conversione tramite un oggetto.È un po' più semplice.

Ho usato la risposta di lobos e funziona.Ma ho avuto un problema con la conversione di raddoppia a causa delle impostazioni culturali.Quindi ho aggiunto

return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);

Ancora un'altra variazione.Gestisce i valori Nullable, nonché le situazioni in cui la stringa è nulla e T lo è non nullabile.

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(); }
    }
}

Con ispirazione da BobLa risposta di , queste estensioni supportano anche la conversione di valori nulli e tutte le conversioni primitive indietro e quarta.

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));
        }
}

Esempi

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

            int? intValue = null;
            var strResult = intValue.Convert<string>();
Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top