我正在构建一个自定义解析器,它应该读取分隔的数据列表,并将结果存储在类中。我的问题是,生成数据的程序并不总是包含所有分隔符。
例如,如果最后3个属性没有值,它将跳过最后3个分隔符。
我一直在使用这样的东西,直到我注意到这个怪癖:
var data = message.Split(delimiter);
if (data.Length < 5)
throw new Exception("Invalid message");
Id = data[0];
Property1 = data[1];
Property2 = data[2];
Property3 = data[3];
Property4 = data[4];
当然,如果分隔的字符串包含少于5个元素,则会产生问题。
将可能错误的分隔字符串解析为类的最佳方法是什么?
我不想对每个属性使用if
语句,因为一些分隔的字符串包含超过50个属性。
我想过创建一个包含所有属性的数组,并在数据数组上运行for-each循环,但是我不确定它的性能影响,并且想先看看是否有更好的方法。 / p>
答案 0 :(得分:3)
假设属性可以为空
Property1 = data.Length > 1 ? data[1] : null;
Property2 = data.Length > 2 ? data[2] : null;
Property3 = data.Length > 3 ? data[3] : null;
Property4 = data.Length > 4 ? data[4] : null;
您可以使用对属性有意义的任何默认值,而不是null
。
编辑:
var dataEx = new string[expectedLength];
data.CopyTo(dataEx, 0);
Property1 = dataEx[1];
Property2 = dataEx[2];
Property3 = dataEx[3];
Property4 = dataEx[4];
答案 1 :(得分:2)
扩展方法怎么样?
public static T GetByIndexOrDefault<T>(this Array array, int index)
{
if (array == null)
{
return default(T);
}
if (index <= array.Length)
{
return (T)array.GetValue(index - 1);
}
return default(T);
}
然后:
string data = "foo1;foo2;foo3;foo4";
string[] splittedData = data.Split(';');
string e1 = splittedData.GetByIndexOrDefault<string>(1); // foo1
string e2 = splittedData.GetByIndexOrDefault<string>(2); // foo2
string e3 = splittedData.GetByIndexOrDefault<string>(3); // foo3
string e4 = splittedData.GetByIndexOrDefault<string>(4); // foo4
string e5 = splittedData.GetByIndexOrDefault<string>(5); // null
答案 2 :(得分:1)
假设您的属性命名方案实际上类似于您的示例,您可以使用反射执行此操作:
var data = message.Split(delimiter);
if (data.Length < 1) throw new Exception("Invalid message");
Id = data[0];
for (var i = 1; i < data.Length; i++)
{
var property = GetType().GetProperty("Property" + i);
property.SetValue(this, data[i], null);
}
确保所有属性都具有可接受的默认状态,以防它们未被message
设置。
答案 3 :(得分:1)
创建属性数组会起作用,即。 Xander的答案,但它仍然不是解决数据不良问题的方法。如果文件中间有一个分隔很少的字段,那么数组中间的属性也会出错。
我认为遇到问题时失败并不是什么问题。如果消息格式错误,那么数据就会很糟糕。如果您不需要创建缺少的字段,则可以随时手动解析消息并修复分隔严重的部分。
如果需要缺少字段,某些应用程序会使用算法来尝试修复错误数据。如果您认为可以修复数据(通过创建新数据或按摩旧数据),您可以创建一个算法来“猜测”丢失的字段。
答案 4 :(得分:0)
我会考虑制作一个属性名称的查找表,将属性的预期索引映射到其属性名称。然后通过反射设置属性。
string[] propertyLookup = { "Property1", "Property2", "Property3", "Property4", "Property5" }; \\ etc etc
string[] parsedValues = message.Split(delimiter);
Foo newFoo = new Foo();
Type fooType = newFoo.GetType();
for (int i = 0; i < parsedValues.Count(); i++)
{
PropertyInfo prop = fooType.GetProperty(propertyLookup[i]);
prop.SetValue(newFoo, parsedValues[i], null);
}
答案 5 :(得分:0)
using System;
using System.Windows.Forms;
using System.Reflection;
namespace DynamicProp
{
public partial class Form1 : Form
{
class Messagage
{
public string ID { get; set; }
public string Property1 { get; set; }
public string Property2 { get; set; }
public string Property3 { get; set; }
public string Property4 { get; set; }
}
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
string[] data = { "hasan", "osman", "ali", "veli", "deli" };
Messagage message = new Messagage();
PropertyInfo[] ozellikler = message.GetType().GetProperties();
int I=0;
foreach (PropertyInfo ozellik in ozellikler)
{
ozellik.SetValue(message, data[I], null);
listBox1.Items.Add("özellik :" + ozellik.Name + " tipi :"+ozellik.GetValue(message,null).ToString());
I++;
}
}
}
}
答案 6 :(得分:0)
提供另一种方式......
如果您有一个默认值,例如空字符串,则可以创建一个List并使用AddRange添加数据字符串中的值。然后,如果尚未使用该特定数据的最大字段数,请使用AddRange和Enumerable.Repeat以默认值填充其余值。
List<string> Results = new List<string>();
int MaxFields = 5;
Results.AddRange(message.Split(delimiter));
if(Results.Count < MaxFields)
Results.AddRange(Enumerable.Repeat(String.Empty,MaxFields - Results.Count));
Id = Results[0];
Property1 = Results[1];
Property2 = Results[2];
Property3 = Results[3];
Property4 = Results[4];