我的特殊问题:
我有一个字符串,它在配置类中指定了aribitrary类型
Config.numberType = "System.Foo";
在哪里Foo
是类型Decimal
或Double
我Type.GetType(Config.numberType)
用来返回相应的类型.
如何从该类型中获得能够使用System.Foo.TryParse()
?
一些其他相关的查询
TryParse()
可以从System.Foo.TryParse()
以及访问foo.TryParse()
.这是否意味着foo
C#中的某种类?这对我来说似乎很奇怪int
,double
等等实际上不仅仅是修饰符关键字.
如何在这些情况下声明变量?- var
似乎并非普遍可用,即仅在本地范围等.
Marc Gravell.. 20
正如许多人所说 - 没有直接路线.我期待一个关闭选项是TypeConverter
:
Type type = typeof(double); string text = "123.45"; object value = TypeDescriptor.GetConverter(type) .ConvertFromInvariantString(text);
当然,您可能需要try
/ catch
处理异常.这就是人生.
正如许多人所说 - 没有直接路线.我期待一个关闭选项是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
的方法与参数化类型参数和返回,或TryParse()
使用技术如由塞巴斯蒂安塞德拉克连接,就可以轻松实现编写客户端代码,与静态类型工作的能力......只要它们匹配或可以从您正在解析的类型转换为.
编辑:我删除了通用实现并清理了此响应以更好地适应最初声明的问题.
注意:如果您只想要给出类型的解析值,Marc Gravell的答案可能是最简洁的.下面的答案向您展示了如何获取方法(即MethodInfo对象以及如何调用它).
以下应该可以工作,至少对于实现公共静态bool 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 Dictionaryif 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 (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("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的作用有误解:它不是"变体"类型(类型对象已经用于此类型),而是将类型的声明语法移动到赋值的右侧.以下声明是等效的:
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 };