Conversión de tipo genérico A PARTIR DE una cadena


Tengo una clase que quiero usar para almacenar "propiedades" para otra clase. Estas propiedades simplemente tienen un nombre y un valor. Idealmente, lo que me gustaría es poder agregar propiedades escritas, de modo que el "valor" devuelto sea siempre del tipo que quiero que sea.

El tipo debe ser siempre un primitivo. Esta clase subclase una clase abstracta que básicamente almacena el nombre y el valor como cadena. La idea es que esta subclase agregará algo de seguridad de tipo a la base clase (además de salvarme en alguna conversión).

Por lo tanto, he creado una clase que es (aproximadamente) esto:

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

Así que la pregunta es:

¿Hay una forma "genérica" de convertir de string a una primitiva?

Parece que no puedo encontrar ninguna interfaz genérica que vincule la conversión en todos los ámbitos (algo como ITryParsable habría sido ideal!).

Author: CRABOLO, 2008-08-12

9 answers

No estoy seguro de si entendí tus intenciones correctamente, pero veamos si esta ayuda.

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-09-09 14:52:52

El método de Lubos hasko falla para nullables. El método a continuación funcionará para nullables. Pero no se me ocurrió. Lo encontré a través de Google: http://web.archive.org/web/20101214042641/http://dogaoztuzun.com/post/C-Generic-Type-Conversion.aspx Crédito a"Tuna Toksoz"

Uso primero:

TConverter.ChangeType<T>(StringValue);  

La clase está abajo.

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)));
    }
}
 60
Author: Tim Coker,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-07 18:18:20

Para muchos tipos (integer, double, DateTime, etc.), hay un método de análisis estático. Puedes invocarlo usando reflexión:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-02-07 18:18:36
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)

TypeDescriptor es la clase que tiene el método GetConvertor que acepta un objeto Type y luego puede llamar al método ConvertFrom para convertir el value para ese objeto especificado.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 07:48:17

Posiblemente podría usar una construcción como una clase traits. De esta manera, tendría una clase helper parametrizada que sabe cómo convertir una cadena a un valor de su propio tipo. Entonces su getter podría verse así:

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

Ahora, debo señalar que mi experiencia con tipos parametrizados se limita a C++ y sus plantillas, pero imagino que hay alguna manera de hacer el mismo tipo de cosas usando genéricos de C#.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2008-08-12 09:51:42

Compruebe la estática Nullable.GetUnderlyingType. - Si el tipo subyacente es null, entonces el parámetro de la plantilla no es Nullable, y podemos usar ese tipo directamente - Si el tipo subyacente no es null, utilice el tipo subyacente en la conversión.

Parece funcionar para mí:

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
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();}
    }
}

Uso la conversión a través de un objeto. Es un poco más simple.

 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2011-05-23 11:03:11

Usé lobos answer y funciona. Pero tuve un problema con la conversión de dobles debido a la configuración de la cultura. Así que añadí

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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-06-03 07:53:13

Otra variación. Maneja Nullables, así como situaciones donde la cadena es null y T es no 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/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-08-07 21:26:54