Dynamic TryParse for all data types

后端 未结 3 494
小蘑菇
小蘑菇 2020-12-21 06:39

I have the need to examine to see if an object can be converted to a specific DataType or not, and came up with this :

public static bool TryParseAll(System         


        
相关标签:
3条回答
  • 2020-12-21 07:18

    Here is my version of generic TryParse method. I believe you can use this version too:

    double pi;
    if(ValueTypeHelper.TryParse("3.14159", out pi)) {
        // .. pi = 3.14159
    }
    ...
    string eStr = "2.71828";
    float e;
    if(eStr.TryParse(out e)) {
        // .. e = 2.71828f
    }
    ...
    static class ValueTypeHelper {
        static IDictionary<Type, Delegate> cache = new Dictionary<Type, Delegate>();
        public static bool TryParse<T>(this string valueStr, out T result) {
            Delegate d = null;
            if(!cache.TryGetValue(typeof(T), out d)) {
                var mInfos = typeof(T).GetMember("TryParse", MemberTypes.Method, BindingFlags.Static | BindingFlags.Public);
                if(mInfos.Length > 0) {
                    var s = Expression.Parameter(typeof(string));
                    var r = Expression.Parameter(typeof(T).MakeByRefType());
                    d = Expression.Lambda<TryParseDelegate<T>>(
                        Expression.Call(mInfos[0] as MethodInfo, s, r), s, r).Compile();
                }
                cache.Add(typeof(T), d);
            }
            result = default(T);
            TryParseDelegate<T> tryParse = d as TryParseDelegate<T>;
            return (tryParse != null) && tryParse(valueStr, out result);
        }
        delegate bool TryParseDelegate<T>(string valueStr, out T result);
    }
    
    0 讨论(0)
  • 2020-12-21 07:18

    I have combined both DmitryG's and RezaRahmati's suggested solutions:

    static class GenericValueConverter
    {
        public static bool TryParse<T>(this string input, out T result)
        {
            bool isConversionSuccessful = false;
            result = default(T);
    
            var converter = TypeDescriptor.GetConverter(typeof(T));
            if (converter != null)
            {
                try
                {
                    result = (T)converter.ConvertFromString(input);
                    isConversionSuccessful = true;
                }
                catch { }
            }
    
            return isConversionSuccessful;
        }
    }
    
    void Main()
    {
        double pi;
        if (GenericValueConverter.TryParse("3,14159", out pi)) //Use right decimal point seperator for local culture
        {
            pi.Dump(); //ConsoleWriteline for LinqPad
            //pi=3,14159
        }
    
        string dtStr = "2016-12-21T16:34:22";
        DateTime dt;
        if (dtStr.TryParse(out dt))
        {
            dt.Dump(); //ConsoleWriteline for LinqPad
            //dt=21.12.2016 16:34:22
        }
    
        string guidStr = "D430831B-03B0-44D5-A971-4E73AF96B5DF";
        Guid guid;
        if (guidStr.TryParse(out guid))
        {
            guid.Dump(); //ConsoleWriteline for LinqPad
            //guid=d430831b-03b0-44d5-a971-4e73af96b5df
        }
    }
    
    0 讨论(0)
  • 2020-12-21 07:32

    You should use the TypeDescriptor class:

    public static T Convert<T>(this string input)
    {
        var converter = TypeDescriptor.GetConverter(typeof(T));
        if(converter != null)
        {
            //Cast ConvertFromString(string text) : object to (T)
            return (T)converter.ConvertFromString(input);
        }
        return default(T);
    }
    

    of course this will throw an exception if the conversion fails so you will want to try/catch it.

    0 讨论(0)
提交回复
热议问题