序列化TSV的类的特定属性

时间:2016-09-20 06:58:58

标签: c# csv

我有一个以下类型的POCO

public class Person{
    public Guid Id { get; set; }
    public string Name { get; set; }
    public string Address { get; set; }
    public int PinCode { get; set; }
    public string Phone { get; set; }
}

我有一个Person的列表,我想将其转换为TSV(制表符分隔值)。但我只想在创建TSV时考虑特定属性。在这种情况下,我只想要IdNamePhone

我用来转换为TSV的代码如下

 public string Serialize(string separator, IEnumerable<Person> objectlist)
{
    string[] fields = new[] { "Id", "Name", "Phone" };
    StringBuilder tsvdata = new StringBuilder();

    string header = string.Join(separator, fields);
    tsvdata.AppendLine(header);
    foreach (var o in objectlist)
        tsvdata.AppendLine(o.Id + separator + o.Person + separator + o.Phone);

    return tsvdata.ToString();
}

我不想静态提及/硬编码要考虑的字段,因为它们将来可能会发生变化。我怎样才能做到这一点?

1 个答案:

答案 0 :(得分:1)

即使您没有使用外部库来创建TSV,您仍然可以使用属性来标记特殊属性(例如那些被遗漏的属性)。然后,您可以使用 reflection 来检查现有的属性和属性。

这是一个完整的例子:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Runtime.Serialization;
using System.Text;

namespace ConsoleApplication1
{
    public class Person
    {
        [DataMember]
        public Guid Id { get; set; }
        [DataMember]
        public string Name { get; set; }
        [IgnoreDataMember]
        public string Address { get; set; }
        [IgnoreDataMember]
        public int PinCode { get; set; }
        [DataMember]
        public string Phone { get; set; }
    }

    class Program
    {
        // list of properties of Person class marked with DataMemeber attribute
        private PropertyInfo[] _personProperties = typeof(Person)
            .GetProperties()
            .Where(x => x.GetCustomAttribute(typeof(DataMemberAttribute)) != null).ToArray();

        public string Serialize(string separator, IEnumerable<Person> objectlist)
        {
            StringBuilder tsvdata = new StringBuilder();

            string header = string.Join(separator, _personProperties.Select(x => x.Name).ToArray());
            tsvdata.AppendLine(header);
            foreach (var o in objectlist)
            {
                List<string> lineValues = new List<string>();
                // enumerate through the properties
                foreach (var pi in _personProperties)
                {
                    lineValues.Add(pi.GetValue(o).ToString());
                }
                tsvdata.AppendLine(string.Join(separator, lineValues.ToArray()));
            }

            return tsvdata.ToString();
        }

        static void Main(string[] args)
        {
            Program p = new Program();
            List<Person> persons = new List<Person> {
                new Person { Id = Guid.NewGuid(), Address = "a1", Name = "name1", Phone = "tel1", PinCode = 1111 },
                new Person { Id = Guid.NewGuid(), Address = "a2", Name = "name2", Phone = "tel2", PinCode = 2222 },
            };
            string serializedString = p.Serialize(", ", persons);
            Console.WriteLine($"result: {serializedString}");
        }
    }
}

此代码包含了POCO类的所有属性,检查它们是否具有特定属性,遗漏了那些属性,并输出其余属性。

您可以根据需要定义自己的属性,这里我刚刚使用System.Runtime.Serialization中的 IgnoreDataMember (用于类似目的)。

请注意,检查现有属性和属性是使用反射,应谨慎使用。性能可能是一个问题,如果代码多次运行大型数据集,它可能会很慢 - 这就是我将personProperties从循环中放到私有成员(计算一次)的原因。