代码之家  ›  专栏  ›  技术社区  ›  mike

C通用字符串解析为任何对象

  •  27
  • mike  · 技术社区  · 14 年前

    我将对象值存储在字符串中,例如,

    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);
    

    我之所以需要这样的功能,是因为我将所述值存储在数据库中,并希望通过查询读取这些值,然后初始化对象的相应属性。这是可能的吗?整个对象没有存储在数据库中,只是一些我想动态读取和设置的字段。我知道我可以静态地完成它,但是这会变得单调、难以维护,并且在读取许多不同的字段/属性时容易出错。

    编辑:奖励积分如果 AWEMEMOS函数 可以使用自定义类来指定接受字符串的构造函数!

    edit2:在我想使用这种类型功能的特定情况下,可以通过propertytype知道目标类型。我认为Enums很容易用这个来解析,例如,

    Type destinationType = info.PropertyType;
    Enum.Parse(destinationType, "MyValue");
    
    4 回复  |  直到 10 年前
        1
  •  36
  •   Marc Gravell    14 年前

    也许首先要尝试的是:

    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);
    }
    
        2
  •  4
  •   RouR    10 年前
    public T Get<T>(string val)
    {
        if (!string.IsNullOrWhiteSpace(val))
            return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
        else 
            return default(T);
    }
    
        3
  •  3
  •   Charlie    13 年前

    下面是一个简单的版本:

    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;
    }
    

    它将识别int和double,但其他所有内容都作为字符串返回。处理枚举的问题是,没有办法知道一个值属于什么枚举,也没有办法知道它是否应该是字符串。其他问题是它不处理日期/时间或小数(您如何区分它们与双精度数?)等。

    如果您愿意这样更改代码:

    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 });
    }
    

    编辑:添加了一个缺少的圆括号

        4
  •  0
  •   Community CDub    8 年前

    我知道这不能回答你的问题,但你看过吗? 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到SQL)。