C# generic string parse to any object

后端 未结 4 462
佛祖请我去吃肉
佛祖请我去吃肉 2021-02-01 04:25

I am storing object values in strings e.g.,

string[] values = new string[] { \"213.4\", \"10\", \"hello\", \"MyValue\"};

is there any way to ge

相关标签:
4条回答
  • 2021-02-01 04:49

    Perhaps the first thing to try is:

    object value = Convert.ChangeType(text, info.PropertyType);
    

    However, this doesn't support extensibility via custom types; if you need that, how about:

    TypeConverter tc = TypeDescriptor.GetConverter(info.PropertyType);
    object value = tc.ConvertFromString(null, CultureInfo.InvariantCulture, text);
    info.SetValue(obj, value, null);
    

    Or:

    info.SetValue(obj, AwesomeFunction("20.53", info.PropertyType), null);
    

    with

    public object AwesomeFunction(string text, Type type) {
        TypeConverter tc = TypeDescriptor.GetConverter(type);
        return tc.ConvertFromString(null, CultureInfo.InvariantCulture, text);
    }
    
    0 讨论(0)
  • 2021-02-01 04:54
    public T Get<T>(string val)
    {
        if (!string.IsNullOrWhiteSpace(val))
            return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
        else 
            return default(T);
    }
    
    0 讨论(0)
  • 2021-02-01 04:54

    I know this doesn't answer your question, but have you looked at Dapper micro ORM?
    It's über-simple (compared to LINQ to SQL or, for that reason, Entity Framework) and does what you want.

    Consider this:

    public class Dog
    {
        public int? Age { get; set; }
        public Guid Id { get; set; }
        public string Name { get; set; }
        public float? Weight { get; set; }    
    }            
    
    var guid = Guid.NewGuid();
    var dog = connection.Query<Dog>("select * from Dogs where Id = @Id",
        new { Id = 42 }
    ).First();
    

    Dapper itself is packaged in a single file and, reportedly, is used by StackOverflow team (apart from Linq to SQL).

    0 讨论(0)
  • 2021-02-01 04:55

    Here's a simple version:

    object ConvertToAny(string input)
    {
        int i;
        if (int.TryParse(input, out i))
            return i;
        double d;
        if (double.TryParse(input, out d))
            return d;
        return input;
    }
    

    It will recognize ints and doubles, but everything else is returned as a string. The problem with handling enums is that there's no way to know what enum a value belongs to and there's no way to tell whether it should be a string or not. Other problems are that it doesn't handle dates/times or decimals (how would you distinguish them from doubles?), etc.

    If you're willing to change your code like this:

    PropertyInfo info = typeof(MyObject).GetProperty("SomeProperty"); 
    info.SetValue(obj, AwesomeFunction("20.53", info.PropertyType), null); 
    

    Then it becomes substantially easier:

    object ConvertToAny(string input, Type target)
    {
        // handle common types
        if (target == typeof(int))
            return int.Parse(input);
        if (target == typeof(double))
            return double.Parse(input);
        ...
        // handle enums
        if (target.BaseType == typeof(Enum))
            return Enum.Parse(target, input);
        // handle anything with a static Parse(string) function
        var parse = target.GetMethod("Parse",
                        System.Reflection.BindingFlags.Static |
                        System.Reflection.BindingFlags.Public,
                        null, new[] { typeof(string) }, null);
        if (parse != null)
            return parse.Invoke(null, new object[] { input });
        // handle types with constructors that take a string
        var constructor = target.GetConstructor(new[] { typeof(string) });
        if (constructor != null)
            return constructor.Invoke(new object[] { input });
    }
    

    Edit: Added a missing parenthesis

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