如何从一个类型到TryParse方法?
我特别的问题:
我有一个字符串,它指定了配置类中的任意类型
Config.numberType = "System.Foo";
Foo
是类似Decimal
或Double
的类型
我使用Type.GetType(Config.numberType)
来返回相应的类型。
我如何从这种类型获得可以使用的System.Foo.TryParse()
?
一些进一步的相关查询
System.Foo.TryParse()
和foo.TryParse()
访问TryParse()
foo.TryParse()
。 这是否意味着foo
是C#中的某种类? 这对我来说似乎很奇怪, int
, double
等实际上不只是修饰符关键字。 var
不是普遍可用的,它似乎只在局部范围等。 正如许多人所说 - 没有直接的路线。 我期望一个关闭选项是TypeConverter
:
Type type = typeof(double);
string text = "123.45";
object value = TypeDescriptor.GetConverter(type)
.ConvertFromInvariantString(text);
当然,你可能需要try
/ catch
来处理异常。 这就是人生。
我如何从这种类型获得可以使用的System.Foo.TryParse()?
您需要使用反射来查找,然后调用静态TryParse()
方法。 并非所有类型都实现此方法 - 因此,如果缺失,您必须决定如何处理它。 您还可以使用System.Convert
将字符串转换为任意类型,假定该字符串实际上是该类型的值的有效表示形式,并且已为其实施了转换。
可以从System.Foo.TryParse()和foo.TryParse()访问TryParse()。 这是否意味着foo是C#中的某种类?
int
, double
等是System.Int32
, System.Double
等的别名 - 它们是C#语言的一部分,如果没有它们,它们会很不舒服。
如何在这些情况下声明变量?
在编译时不知道类型,你将被迫声明和使用你的数据作为object
/ System.Object
。 C#4.0将会引入实际的动态类型,这些动态类型将会为你处理一些乏味的反射工作,但是现在你被困在手工中。 请注意,如果您在具有参数化类型参数和返回值的方法中使用System.Convert
,或者使用诸如Sebastian Sedlak链接的技术的TryParse()
方法,则可以轻松实现编写与静态类型一起使用的客户端代码的功能...只要它们匹配或可以从您正在解析的类型转换为。
编辑:我删除了通用实现,并清理了这个响应,以更好地适应最初陈述的问题。
注:Marc Gravell的答案可能是最简洁的,如果你只是想要给出类型的解析值。 下面的答案显示了如何获取方法(即MethodInfo对象以及如何调用它)。
以下应该工作,至少对于实现公共静态布尔TryParse(字符串,T值)的类型:
public static class Parsing
{
static MethodInfo findTryParseMethod(Type type)
{
//find member of type with signature 'static public bool TryParse(string, out T)'
BindingFlags access = BindingFlags.Static | BindingFlags.Public;
MemberInfo[] candidates = type.FindMembers(
MemberTypes.Method,
access,
delegate(MemberInfo m, object o_ignored)
{
MethodInfo method = (MethodInfo)m;
if (method.Name != "TryParse") return false;
if (method.ReturnParameter.ParameterType != typeof(bool)) return false;
ParameterInfo[] parms = method.GetParameters();
if (parms.Length != 2) return false;
if (parms[0].ParameterType != typeof(string)) return false;
if (parms[1].ParameterType != type.MakeByRefType()) return false;
if (!parms[1].IsOut) return false;
return true;
}, null);
if (candidates.Length > 1)
{
//change this to your favorite exception or use an assertion
throw new System.Exception(String.Format(
"Found more than one method with signature 'public static bool TryParse(string, out {0})' in type {0}.",
type));
}
if (candidates.Length == 0)
{
//This type does not contain a TryParse method - replace this by your error handling of choice
throw new System.Exception(String.Format(
"Found no method with signature 'public static bool TryParse(string, out {0})' in type {0}.",
type));
}
return (MethodInfo)candidates[0];
}
public static bool TryParse(Type t, string s, out object val)
{
MethodInfo method = findTryParseMethod(t); //can also cache 'method' in a Dictionary<Type, MethodInfo> if desired
object[] oArgs = new object[] { s, null };
bool bRes = (bool)method.Invoke(null, oArgs);
val = oArgs[1];
return bRes;
}
//if you want to use TryParse in a generic syntax:
public static bool TryParseGeneric<T>(string s, out T val)
{
object oVal;
bool bRes = TryParse(typeof(T), s, out oVal);
val = (T)oVal;
return bRes;
}
}
使用以下测试代码:
public bool test()
{
try
{
object oVal;
bool b = Parsing.TryParse(typeof(int), "123", out oVal);
if (!b) return false;
int x = (int)oVal;
if (x!= 123) return false;
}
catch (System.Exception)
{
return false;
}
try
{
int x;
bool b = Parsing.TryParseGeneric<int>("123", out x);
if (!b) return false;
if (x != 123) return false;
}
catch (System.Exception)
{
return false;
}
try
{
object oVal;
bool b = Parsing.TryParse(typeof(string), "123", out oVal);
//should throw an exception (//no method String.TryParse(string s, out string val)
return false;
}
catch (System.Exception)
{
//should throw an exception
}
return true;
}
}
并在你的情况下使用它:
//input: string s, Config
Type tNum = Type.GetType(Config.numberType);
object oVal;
bool ok = Parsing.TryParse(tNum, s, out oVal);
//oVal is now of type tNum and its value is properly defined if ok == true
关于var的使用:你可能会误解var的作用:它不是一个“variant”类型(类型对象已经用于此类型),而是将类型的声明语法移到了作业的右侧。 以下声明是等效的:
var i = 1; //the compiler infers the type from the assignment, type of i is int.
int i = 1; //type of i is int via declaration
var的主要用途是允许创建匿名类型:
var anon = new { Name = "abc", X = 123 };
链接地址: http://www.djcxy.com/p/21057.html
上一篇: How do I get from a type to the TryParse method?
下一篇: How can I set the value of auto property backing fields in a struct constructor?