我试图创建一个通用扩展,使用'TryParse'来检查字符串是否为给定类型:
public static bool Is<T>(this string input)
{
T notUsed;
return T.TryParse(input, out notUsed);
}
这将无法编译,因为它无法解析符号TryParse
据我所知,“TryParse”不是任何接口的一部分。
这有可能吗?
更新:
使用以下我想出的答案:
public static bool Is<T>(this string input)
{
try
{
TypeDescriptor.GetConverter(typeof(T)).ConvertFromString(input);
}
catch
{
return false;
}
return true;
}
它工作得很好,但我认为以这种方式使用异常对我来说不合适。
更新2:
修改为传递类型而不是使用泛型:
public static bool Is(this string input, Type targetType)
{
try
{
TypeDescriptor.GetConverter(targetType).ConvertFromString(input);
return true;
}
catch
{
return false;
}
}
有点晚了,但这是我想到的。无异常,一次性(每种类型)反射。
public static class Extensions {
public static T? ParseAs<T>(this string str) where T : struct {
T val;
return GenericHelper<T>.TryParse(str, out val) ? val : default(T?);
}
public static T ParseAs<T>(this string str, T defaultVal) {
T val;
return GenericHelper<T>.TryParse(str, out val) ? val : defaultVal;
}
private static class GenericHelper<T> {
public delegate bool TryParseFunc(string str, out T result);
private static TryParseFunc tryParse;
public static TryParseFunc TryParse {
get {
if (tryParse == null)
tryParse = Delegate.CreateDelegate(
typeof(TryParseFunc), typeof(T), "TryParse") as TryParseFunc;
return tryParse;
}
}
}
}
额外的类是必需的,因为泛型类中不允许使用扩展方法。这允许简单的使用,如下所示,并且只在第一次使用类型时命中反射。
"5643".ParseAs<int>()
我使用Charlie Brown的答案作为Json.NET的JObject扩展方法。
public static class JObjectExtension
{
public delegate bool TryParseHandler<T>(string value, out T result);
public static bool TryParsePropertyAs<T>(
this JObject jObject,
string propertyName,
TryParseHandler<T> parser,
out T value)
{
value = default;
if (!jObject.TryGetValue(propertyName, out var jToken)) return false;
if (!parser(jToken.Value<string>(), out T result)) return false;
value = result;
return true;
}
}
如果你设置使用TryParse,你可以使用反射并像这样做:
public static bool Is<T>(this string input)
{
var type = typeof (T);
var temp = default(T);
var method = type.GetMethod(
"TryParse",
new[]
{
typeof (string),
Type.GetType(string.Format("{0}&", type.FullName))
});
return (bool) method.Invoke(null, new object[] {input, temp});
}