Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/string/5.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# C通用字符串解析到任何对象_C#_String_Parsing_Generics - Fatal编程技术网

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

C# C通用字符串解析到任何对象,c#,string,parsing,generics,C#,String,Parsing,Generics,我将对象值存储在字符串中,例如 string[] values = new string[] { "213.4", "10", "hello", "MyValue"}; 是否有任何方法可以通用地初始化适当的对象类型?e、 g.差不多 double foo1 = AwesomeFunction(values[0]); int foo2 = AwesomeFunction(values[1]); string foo3 = AwesomeFunction(values[2]); MyEnum fo

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

string[] values = new string[] { "213.4", "10", "hello", "MyValue"};
是否有任何方法可以通用地初始化适当的对象类型?e、 g.差不多

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

以下是一个简单的版本:

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

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

也许首先要尝试的是:

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


我知道这不能回答你的问题,但你看过吗? 与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本身被打包在一个和中,据报道,除了Linq到SQL之外。

而且无论如何,这样的函数和您所做的将返回对象,所以OP应该转换为某种类型:intConvertToAny1。换句话说,IMO-这不可能/这项任务毫无意义。只有CLR,而不是C可以包含仅通过返回类型不同的函数。有关其他信息,请参见EDIT2。在我的特定用途中,我可以通过PropertyType属性获取目标类类型。这将使解析枚举变得简单。它还可以区分浮点数/双精度数/小数等。然而,我希望避免为每种类类型编写一个大的if/case语句,尽管我想它不会那么混乱。myrne:Marc的答案可能更好,但我修改了我的,以支持枚举,带字符串的构造函数,还有任何有解析功能的东西。是的,你的现在看起来更整洁了。这两种方法都会奏效,尽管Marc的方法在我看来有点整洁。我现在唯一想知道的是,这两种方法是否会比另一种方法慢很多。我不认为速度会是一个很大的问题,除非它需要几秒钟而不是几毫秒,但知道它会很有趣。我将不得不运行一些tests.re奖励点-最好定义并关联一个TypeConverter,并让它处理向构造函数的转发。因为这就是类型转换器的设计目的…哇,快速回复!看起来这个代码很管用。那个TypeConverter类很不错,和我想要的差不多。谢谢+1.PS:对于OP的编辑:如果您有int/double/etc之外的其他自定义类,您可以编写相应的TypeConverter。检查并@mrnye-有关信息,您可以非常轻松地编写自己的类型转换器-只需使用[TypeConverter…]注释您的自定义类型,告诉它您想要什么。你甚至可以改变现有类型的转换器,如果你喜欢…@Danny-好链接,ta。如果类型不在您的控制范围内,即您无法在源位置添加属性,您还可以在运行时使用TypeDescriptor.AddAttributes关联自定义转换器。@Danny@Marc谢谢,这些链接很好。我想我会沿着这条路走下去,为我的每个类实现一个TypeDescriptor,因为只有十几个左右的自定义类,所以这是一个相当轻松的过程。其他一切都是枚举或基本类,它们似乎都与此方法一起工作。这将是一个很好的解释,说明此代码的作用,而不是仅仅将代码字符串解析粘贴到任何泛型上,对于那些想了解此答案中的情况的人来说。
public T Get<T>(string val)
{
    if (!string.IsNullOrWhiteSpace(val))
        return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
    else 
        return default(T);
}
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();
public T Get<T>(string val)
{
    if (!string.IsNullOrWhiteSpace(val))
        return (T) TypeDescriptor.GetConverter(typeof (T)).ConvertFromString(val);
    else 
        return default(T);
}