我将对象值存储在字符串中,例如,
string[] values = new string[] { "213.4", "10", "hello", "MyValue"};
有没有办法一般初始化适当的对象类型?例如,像
double foo1 = AwesomeFunction(values[0]);
int foo2 = AwesomeFunction(values[1]);
string foo3 = AwesomeFunction(values[2]);
MyEnum foo4 = AwesomeFunction(values[3]);
其中AwesomeFunction
是我需要的功能。最终用途是初始化属性,例如,
MyObject obj = new MyObject();
PropertyInfo info = typeof(MyObject).GetProperty("SomeProperty");
info.SetValue(obj, AwesomeFunction("20.53"), null);
我需要这样的功能的原因是我将所述值存储在数据库中,并希望通过查询读出它们,然后初始化对象的相应属性。这有可能吗?整个对象没有存储在数据库中,只是我想阅读的几个字段&动态设置。我知道我可以静态地做到这一点,但是这将变得乏味,难以维护,并且正在阅读许多不同领域/属性的错误。
编辑:如果AwesomeFunction
可以使用指定接受字符串的构造函数的自定义类,则可以使用加分点。
EDIT2:在我想要使用此类功能的特定情况下,可以通过PropertyType了解目标类型。我认为枚举很容易解析,例如,
Type destinationType = info.PropertyType;
Enum.Parse(destinationType, "MyValue");
答案 0 :(得分:36)
也许首先要尝试的是:
object value = Convert.ChangeType(text, info.PropertyType);
但是,这不支持通过自定义类型的可扩展性; 如果你需要,那该怎么样:
TypeConverter tc = TypeDescriptor.GetConverter(info.PropertyType);
object value = tc.ConvertFromString(null, CultureInfo.InvariantCulture, text);
info.SetValue(obj, value, null);
或者:
info.SetValue(obj, AwesomeFunction("20.53", info.PropertyType), null);
与
public object AwesomeFunction(string text, Type type) {
TypeConverter tc = TypeDescriptor.GetConverter(type);
return tc.ConvertFromString(null, CultureInfo.InvariantCulture, text);
}
答案 1 :(得分:4)
public T Get<T>(string val)
{
if (!string.IsNullOrWhiteSpace(val))
return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
else
return default(T);
}
答案 2 :(得分:3)
这是一个简单的版本:
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;
}
它将识别整数和双精度数,但其他所有内容都以字符串形式返回。处理枚举的问题在于,无法知道值属于哪个枚举,并且无法判断它是否应该是字符串。其他问题是它不处理日期/时间或小数(你如何区分它们与双打?)等。
如果您愿意更改代码,请执行以下操作:
PropertyInfo info = typeof(MyObject).GetProperty("SomeProperty");
info.SetValue(obj, AwesomeFunction("20.53", info.PropertyType), null);
然后它变得非常容易:
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 });
}
编辑:添加了缺失的括号
答案 3 :(得分:0)
我知道这不能回答你的问题,但是你看过Dapper micro ORM吗? 这是简单的(与LINQ to SQL相比,或者,出于这个原因,实体框架)并且做你想要的。
考虑一下:
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本身打包在single file中,据说是is used by StackOverflow team(除了Linq to SQL)。