type tipos operator objetos datos convert conversion cast another c# .net type-conversion

tipos - C#: análisis dinámico de System.Type



conversion de tipos de datos en c# (6)

Tengo un Tipo, una Cadena y un Objeto.

¿Hay alguna manera de llamar al método de análisis sintáctico o convertir ese tipo en la cadena de forma dinámica?

Básicamente, ¿cómo elimino las sentencias if en esta lógica?

object value = new object(); String myString = "something"; Type propType = p.PropertyType; if(propType == Type.GetType("DateTime")) { value = DateTime.Parse(myString); } if (propType == Type.GetType("int")) { value = int.Parse(myString); }

Y haz algo más así.

object value = new object(); String myString = "something"; Type propType = p.PropertyType; //this doesn''t actually work value = propType .Parse(myString);


Depende de lo que le gustaría lograr.

1) si simplemente está tratando de limpiar su código, y eliminar la verificación de tipo repetitiva, entonces lo que quiere hacer es centralizar sus cheques en un método, comme

public static T To<T> (this string stringValue) { T value = default (T); if (typeof (T) == typeof (DateTime)) { // insert custom or convention System.DateTime // deserialization here ... } // ... add other explicit support here else { throw new NotSupportedException ( string.Format ( "Cannot convert type [{0}] with value [{1}] to type [{2}]." + " [{2}] is not supported.", stringValue.GetType (), stringValue, typeof (T))); } return value; }

2) si desea algo más general para los tipos básicos, podría intentar algo como lo suggests , aunque, en verdad, no lo he intentado yo mismo, no estoy familiarizado con las extensiones [recientes] de Convert . También una muy buena sugerencia.

3) de hecho, es probable que desee fusionar tanto el 1) como el 2) anteriores en una única extensión que le permita respaldar la conversión de valores básicos y la compatibilidad con tipos complejos explícitos.

4) si quieres estar completamente "manos libres", entonces también puedes usar la antigua deserialización simple [Xml o Binary, ya sea / o]. Por supuesto, esto restringe su entrada, es decir, todas las entradas deben estar en un formato Xml o Binario apropiado. Honestamente, esto es probablemente excesivo, pero vale la pena mencionarlo.

Por supuesto, todos estos métodos hacen esencialmente lo mismo. No hay magia en ninguno de ellos, en algún momento alguien está realizando una búsqueda lineal [si es una búsqueda implícita a través de cláusulas si consecutivas o bajo el capó a través de las instalaciones de conversión. Serialización].

5) si desea mejorar el rendimiento, lo que desea hacer es mejorar la parte de "búsqueda" de su proceso de conversión. Cree una lista explícita de "tipos soportados", cada tipo corresponde a un índice en una matriz. En lugar de especificar el Tipo en una llamada, usted especifica el índice.

EDITAR: así, mientras que la búsqueda lineal es prolija y rápida, también se me ocurre que sería aún más rápido si el consumidor simplemente obtuviera funciones de conversión y las invocara directamente. Es decir, el consumidor sabe de qué tipo le gustaría convertir a [esto es un hecho], por lo que si necesita convertir muchos elementos a la vez,

// S == source type // T == target type public interface IConvert<S> { // consumers/infrastructure may now add support int AddConversion<T> (Func<S, T> conversion); // gets conversion method for local consumption Func<S, T> GetConversion<T> (); // easy to use, linear look up for one-off conversions T To<T> (S value); } public class Convert<S> : IConvert<S> { private class ConversionRule { public Type SupportedType { get; set; } public Func<S, object> Conversion { get; set; } } private readonly List<ConversionRule> _map = new List<ConversionRule> (); private readonly object _syncRoot = new object (); public void AddConversion<T> (Func<S, T> conversion) { lock (_syncRoot) { if (_map.Any (c => c.SupportedType.Equals (typeof (T)))) { throw new ArgumentException ( string.Format ( "Conversion from [{0}] to [{1}] already exists. " + "Cannot add new conversion.", typeof (S), typeof (T))); } ConversionRule conversionRule = new ConversionRule { SupportedType = typeof(T), Conversion = (s) => conversion (s), }; _map.Add (conversionRule); } } public Func<S, T> GetConversion<T> () { Func<S, T> conversionMethod = null; lock (_syncRoot) { ConversionRule conversion = _map. SingleOrDefault (c => c.SupportedType.Equals (typeof (T))); if (conversion == null) { throw new NotSupportedException ( string.Format ( "Conversion from [{0}] to [{1}] is not supported. " + "Cannot get conversion.", typeof (S), typeof (T))); } conversionMethod = (value) => ConvertWrap<T> (conversion.Conversion, value); } return conversionMethod; } public T To<T> (S value) { Func<S, T> conversion = GetConversion<T> (); T typedValue = conversion (value); return typedValue; } // private methods private T ConvertWrap<T> (Func<S, object> conversion, S value) { object untypedValue = null; try { untypedValue = conversion (value); } catch (Exception exception) { throw new ArgumentException ( string.Format ( "Unexpected exception encountered during conversion. " + "Cannot convert [{0}] [{1}] to [{2}].", typeof (S), value, typeof (T)), exception); } if (!(untypedValue is T)) { throw new InvalidCastException ( string.Format ( "Converted [{0}] [{1}] to [{2}] [{3}], " + "not of expected type [{4}]. Conversion failed.", typeof (S), value, untypedValue.GetType (), untypedValue, typeof (T))); } T typedValue = (T)(untypedValue); return typedValue; } }

y se usaría como

// as part of application innitialization IConvert<string> stringConverter = container.Resolve<IConvert<string>> (); stringConverter.AddConversion<int> (s => Convert.ToInt32 (s)); stringConverter.AddConversion<Color> (s => CustomColorParser (s)); ... // a consumer elsewhere in code, say a Command acting on // string input fields of a form // // NOTE: stringConverter could be injected as part of DI // framework, or obtained directly from IoC container as above int someCount = stringConverter.To<int> (someCountString); Func<string, Color> ToColor = stringConverter.GetConversion <Color> (); IEnumerable<Color> colors = colorStrings.Select (s => ToColor (s));

Prefiero este último enfoque, porque te da un control completo sobre la conversión. Si usa un contenedor de Inversión de Control [IoC] como Castle Windsor o Unity, entonces la inyección de este servicio se realiza para usted. Además, como está basado en instancias , puede tener varias instancias, cada una con su propio conjunto de reglas de conversión, por ejemplo, si tiene múltiples controles de usuario, cada uno generando su propio DateTime u otro formato de cadena complejo.

Diablos, incluso si quisiera soportar múltiples reglas de conversión para un solo tipo de objetivo, eso también es posible, simplemente tiene que extender los parámetros del método para especificar cuál.


Esto debería funcionar para todos los tipos primitivos, y para los tipos que implementan IConvertible

public static T ConvertTo<T>(object value) { return (T)Convert.ChangeType(value, typeof(T)); }

EDITAR: en realidad en su caso, no puede usar genéricos (al menos no fácil). En cambio, podrías hacer eso:

object value = Convert.ChangeType(myString, propType);


Me encontré con este problema y así es como lo resolví:

value = myString; var parse = propType.GetMethod("Parse", new[] { typeof(string) }); if (parse != null) { value = parse.Invoke(null, new object[] { value }); }

...Y funcionó para mí.

Para resumir, está tratando de encontrar un método estático "Parse" en el tipo de objeto que toma solo una cadena como argumento. Si encuentra un método así, inícielo con el parámetro de cadena que está tratando de convertir. Como p es PropertyInfo para mi tipo, finalicé este método estableciendo mi instancia con el valor de la siguiente manera:

p.SetValue(instance, value, null);


Parece que lo que quieres hacer (al menos si los tipos implicados son tipos a los que no puedes modificar la fuente) requeriría el tipado de pato que no está en C #

Si necesita hacer esto mucho, incluiría la lógica en una clase o método en el que puede pasar "myString" y "propType" a y devolvería valor. En ese método, simplemente haría la cadena if que tiene arriba y devolverá el valor cuando encuentre una que coincida. Tendría que listar manualmente todos los tipos posibles, pero solo tendría que hacerlo una vez.


Técnicamente es imposible mirar una cuerda y saber con certeza qué tipo representa.

Entonces, para cualquier enfoque genérico, necesitarás al menos:

  1. la cadena a ser analizada
  2. el tipo usado para analizar.

Eche un vistazo al método estático Convert.ChangeType() .


TypeDescriptor para rescatar:

var converter = TypeDescriptor.GetConverter(propType); var result = converter.ConvertFrom(myString);

Para integrarse en la infraestructura de TypeConverter , implemente su propio TypeConverter y decore la clase que se convertirá con él con TypeConverterAttribute