Estoy tratando de crear una extensión genérica que use 'TryParse' para verificar si una cadena es de un tipo dado:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
esto no se compilará ya que no puede resolver el símbolo 'TryParse'
Según tengo entendido, 'TryParse' no es parte de ninguna interfaz.
¿Es esto posible hacer en absoluto?
Actualizar:
Usando las respuestas a continuación, se me ocurrió:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
Funciona bastante bien, pero creo que usar excepciones de esa manera no me parece correcto.
Actualización2:
Modificado para pasar el tipo en lugar de usar genéricos:
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
protected Boolean TryParse<T>(Object value, out T result) { result = default(T); var convertor = TypeDescriptor.GetConverter(typeof(T)); if (convertor == null || !convertor.IsValid(value)) { return false; } result = (T)convertor.ConvertFrom(value); return true; }
ConvertFrom(value)
método en untry-catch
bloque para detectar las excepciones.Respuestas:
Debe usar la clase TypeDescriptor :
fuente
También solicité un TryParse genérico recientemente. Esto es lo que se me ocurrió;
Entonces es simplemente una cuestión de llamar así:
fuente
T
del controlador, y tenemos que especificar explícitamenteT
cuándo lo llamamos. Tengo curiosidad, ¿por qué no puede inferirT
?SomeMethod(TryParse<int>(DollarTextbox.Text, int.TryParse))
sin crear una variable de salida para captar el resultadoint.TryParse
. Sin embargo, estoy de acuerdo con el sentimiento de Nick sobre hacer que la función infiera el tipo.Usar try / catches para controlar el flujo es una política terrible. Lanzar una excepción provoca retrasos en el rendimiento mientras el tiempo de ejecución funciona alrededor de la excepción. En su lugar, valide los datos antes de convertir.
fuente
converter != null
siempre es cierto, por lo que se puede eliminar del código.Si está configurado con TryParse, puede usar la reflexión y hacerlo así:
fuente
Type.GetType(string.Format(...))
contype.MakeByRefType()
.Esto usa un constructor estático para cada tipo genérico, por lo que solo tiene que hacer el trabajo costoso la primera vez que lo llama en un tipo dado. Maneja todos los tipos en el espacio de nombres del sistema que tienen métodos TryParse. También funciona con versiones anulables de cada una de ellas (que son estructuras) a excepción de las enumeraciones.
fuente
¿Qué tal algo como esto?
http://madskristensen.net/post/Universal-data-type-checker.aspx ( Archivo )
Esto se puede convertir a un método genérico con bastante facilidad.
fuente
catch { }
. Sin embargo, en este caso no hay alternativa, porque .NETBaseNumberConverter
arroja laException
clase base en caso de un error de conversión. Esto es muy desafortunado. De hecho, todavía hay bastantes lugares donde se lanza este tipo base. Esperemos que Microsoft los arregle en una versión futura del marco.No puedes hacerlo en tipos generales.
Lo que puede hacer es crear una interfaz ITryParsable y usarla para tipos personalizados que implementan esta interfaz.
Sin embargo, supongo que tienes la intención de usar esto con tipos básicos como
int
yDateTime
. No puede cambiar estos tipos para implementar nuevas interfaces.fuente
dynamic
palabra clave, porque no funcionará en la escritura estática. Puede crear su propio objeto dinámico que pueda manejar esto, pero no es el predeterminado.Inspirado por la solución publicada aquí por Charlie Brown, creé un TryParse genérico utilizando una reflexión que opcionalmente genera el valor analizado:
Se le puede llamar así:
Actualización:
también gracias a la solución de YotaXP que realmente me gusta, creé una versión que no usa métodos de extensión pero que aún tiene un singleton, minimizando la necesidad de hacer una reflexión:
Llámalo así:
fuente
Bastante tarde para la fiesta, pero esto es lo que se me ocurrió. Sin excepciones, reflexión única (por tipo).
La clase adicional es necesaria porque los métodos de extensión no están permitidos dentro de las clases genéricas. Esto permite un uso simple, como se muestra a continuación, y solo alcanza el reflejo la primera vez que se usa un tipo.
fuente
Aquí hay otra opción.
Escribí una clase que facilita el registro de cualquier número de
TryParse
controladores. Me permite hacer esto:Me
42
imprimen en la consola.La clase es:
fuente
Cuando quise hacer casi exactamente esto, tuve que implementarlo de la manera difícil, dada la reflexión. Dado
T
, reflexionetypeof(T)
y busque un métodoTryParse
oParse
, invocándolo si lo ha encontrado.fuente
Este es mi intento. Lo hice como un "ejercicio". Traté de hacerlo tan similar al uso como los existentes " Convert.ToX () " -ones, etc. Pero este es el método de extensión:
fuente
TypeConverter.ConvertFrom()
es que la clase fuente tiene que proporcionar la conversión de tipo, lo que generalmente significa que no puede admitir la conversión a tipos personalizados.Como dijiste,
TryParse
no es parte de una interfaz. Tampoco es miembro de ninguna clase base dada, ya que es realmentestatic
y lasstatic
funciones no pueden serlovirtual
. Por lo tanto, el compilador no tiene forma de asegurar que enT
realidad tiene un miembro llamadoTryParse
, por lo que esto no funciona.Como dijo @Mark, podría crear su propia interfaz y usar tipos personalizados, pero no tiene suerte para los tipos incorporados.
fuente
fuente
Esta es una cuestión de 'restricciones genéricas'. Debido a que no tiene una interfaz específica, está atascado a menos que siga las sugerencias de la respuesta anterior.
Para obtener documentación al respecto, consulte el siguiente enlace:
http://msdn.microsoft.com/en-us/library/ms379564(VS.80).aspx
Le muestra cómo usar estas restricciones y debería darle algunas pistas más.
fuente
Tomado de http://blogs.msdn.com/b/davidebb/archive/2009/10/23/using-c-dynamic-to-call-static-members.aspx
al seguir esta referencia: ¿Cómo invocar el método estático en C # 4.0 con tipo dinámico?
Y úsalo de la siguiente manera:
fuente
Logré conseguir algo que funciona así
Aquí está mi código
StaticMembersDynamicWrapper está adaptado del artículo de David Ebbo (arrojaba una AmbiguousMatchException)
fuente
fuente
Con el
TypeDescriptor
uso de la clase deTryParse
manera relacionada:fuente
Usando la información anterior, esto es lo que desarrollé. Convertirá el objeto directamente es posible, de lo contrario, convertirá el objeto en una cadena y llamará al método TryParse para el tipo de objeto deseado.
Guardo en caché los métodos en un diccionario, ya que cada uno se encuentra para reducir la carga de obtención de métodos.
Es posible probar si el objeto se puede convertir directamente al tipo de destino, lo que reduciría aún más la parte de conversión de cadena. Pero lo dejaré fuera por ahora.
fuente
Puse un montón de ideas aquí juntas y terminé con una solución muy corta.
Este es un método de extensión en una cadena
Lo hice con la misma huella que los métodos TryParse en los tipos numéricos
'' '
fuente
T. TryParse ... ¿por qué?
No veo ningún beneficio en tener esa
TryParse
función genérica . Hay demasiadas estrategias diferentes para analizar y convertir datos entre diferentes tipos, con un posible comportamiento conflictivo. ¿Cómo podría esta función saber qué estrategia elegir de una manera libre de contexto?Convert.ChangeType
. Esta API es personalizable en tiempo de ejecución. ¿Su función requiere un comportamiento predeterminado o permite la personalización?fuente
Una versión para obtener descendientes de XDocument.
fuente