c# - una - Tipo genérico de conversión de cadena
convertir tipo string a int c# (9)
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 siempre debe ser un primitivo. Esta clase clasifica una clase abstracta que básicamente almacena el nombre y el valor como una cadena. La idea es que esta subclase agregará algo de seguridad de tipo a la clase base (además de guardarme en alguna conversión).
Entonces, he creado una clase que es (aproximadamente) esta:
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 una cadena a una primitiva?
Parece que no puedo encontrar ninguna interfaz genérica que vincule la conversión en general (¡algo como ITryParsable hubiera sido ideal!).
Compruebe la estática Nullable.GetUnderlyingType
. - Si el tipo subyacente es nulo, entonces el parámetro de la plantilla no es Nullable
, y podemos usar ese tipo directamente - Si el tipo subyacente no es nulo, use el tipo subyacente en la conversión.
Parece funcionar para mi:
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");
}
El método de lubos hasko falla para nullables. El siguiente método funcionará para nullables. Aunque no se me ocurrió. Lo encontré en 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)));
}
}
No estoy seguro de si entendí sus intenciones correctamente, pero veamos si esto 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();}
}
}
Otra variación más. Maneja Nullables, así como situaciones donde la cadena es nula y T no es anulable.
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(); }
}
}
Para muchos tipos (entero, doble, DateTime, etc.), hay un método Parse estático. Puedes invocarlo mediante reflexión:
MethodInfo m = typeof(T).GetMethod("Parse", new Type[] { typeof(string) } );
if (m != null)
{
return m.Invoke(null, new object[] { base.Value });
}
Posiblemente podrías usar una construcción como una clase de rasgos . De esta manera, tendría una clase auxiliar parametrizada que sabe cómo convertir una cadena a un valor de su propio tipo. Entonces tu captador podría verse así:
get { return StringConverter<DataType>.FromString(base.Value); }
Ahora, debo señalar que mi experiencia con los tipos parametrizados se limita a C ++ y sus plantillas, pero imagino que hay alguna manera de hacer lo mismo con los genéricos de C #.
Usé la respuesta de los lobos y funciona. Pero tuve un problema con la conversión de dobles debido a la configuración de la cultura. Así que agregué
return (T)Convert.ChangeType(base.Value, typeof(T), CultureInfo.InvariantCulture);
TypeDescriptor.GetConverter(PropertyObject).ConvertFrom(Value)
TypeDescriptor
es una clase que tiene el método GetConvertor
que acepta un objeto Type
y luego puede llamar al método ConvertFrom
para convertir el value
de ese objeto especificado.
public class TypedProperty<T> : Property
{
public T TypedValue
{
get { return (T)(object)base.Value; }
set { base.Value = value.ToString();}
}
}
Utilizando la conversión a través de un objeto. Es un poco más simple.