I am storing object values in strings e.g.,
string[] values = new string[] { \"213.4\", \"10\", \"hello\", \"MyValue\"};
is there any way to ge
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);
}
public T Get<T>(string val)
{
if (!string.IsNullOrWhiteSpace(val))
return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
else
return default(T);
}
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).
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