如何从一个类型到TryParse方法?

我特别的问题:

我有一个字符串,它指定了配置类中的任意类型

Config.numberType = "System.Foo";

Foo是类似DecimalDouble的类型

我使用Type.GetType(Config.numberType)来返回相应的类型。

我如何从这种类型获得可以使用的System.Foo.TryParse()

一些进一步的相关查询

  • 可以从System.Foo.TryParse()foo.TryParse()访问TryParse() foo.TryParse() 。 这是否意味着foo是C#中的某种类? 这对我来说似乎很奇怪, intdouble等实际上不只是修饰符关键字。
  • 如何在这些情况下声明变量? - 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#中的某种类?

    intdouble等是System.Int32System.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?