当前位置: 首页 > 编程语言 > C#

CSV的通用类(所有属性)Share

时间:2023-04-10 18:02:18 C#

CSV的通用类(所有属性)我想要的是我可以将任何类(它的所有实例)导出到CSV。有人可以指导我找到一个可能的解决方案吗(如果已经证明)。谢谢!实际上,这里已经解决了一个类似的问题:BestpracticesforserializingobjectsintocustomstringformatsforuseinoutputfilesDidthisworkforyou?有一个使用反射提取字段名称和值并将它们附加到字符串的示例。看看LINQtoCSV。虽然它有点重,这就是为什么我编写了以下代码来执行我需要的一小部分功能。它可以像您要??求的那样处理属性和字段,尽管不是很多。它所做的其中一件事是在包含逗号、引号或换行符的情况下正确转义输出。publicstaticclassCsvSerializer{//////将对象序列化为逗号分隔值(CSV)格式[1]。//////与其尝试使用此///函数序列化任意复杂类型,不如在给定类型A的情况下指定一个新类型A'。///让A'的构造函数接受A类型的对象,然后将///相关值分配给///A'对象上适当命名的字段或属性。//////[1]http://tools.ietf.org/html/rfc4180///publicstaticvoidSerialize(TextWriteroutput,IEnumerableobjects){varfields=frommiintypeof(T).GetMembers(BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static)wherenew[]{MemberTypes.Field,MemberTypes.Property}.Contains(mi.MemberType)让orderAttr=(ColumnOrderAttribute)Attribute.GetCustomAttribute(mi,typeof(ColumnOrderAttribute))orderbyorderAttr==null?int.MaxValue:orderAttr.Order,mi.Name选择mi;output.WriteLine(QuoteRecord(fields.Select(f=>f.N我)));foreach(对象中的var记录){output.WriteLine(QuoteRecord(FormatObject(fields,record)));}}staticIEnumerableFormatObject(IEnumerablefields,Trecord){foreach(varfieldinfields){if(fieldisFieldInfo){varfi=(FieldInfo)field;yieldreturnConvert.ToString(fi.GetValue(record));}elseif(fieldisPropertyInfo){varpi=(PropertyInfo)field;yieldreturnConvert.ToString(pi.GetValue(record,null));}else{thrownewException("未处理的案例。");}}}常量字符串CsvSeparator=",";staticstringQuoteRecord(IEnumerablerecord){returnString.Join(CsvSeparator,record.Select(field=>QuoteField(field)).ToArray());}staticstringQuoteField(stringfield){if(String.IsNullOrEmpty(field)){return"""";}elseif(field.Contains(CsvSeparator)||field.Contains(""")||field.Contains("r")||field.Contains("n")){returnString.Format(""{0}"",field.Replace(""",""""));}else{返回字段;}}[属性用法(属性目标.Field|AttributeTargets.Property)]publicclassColumnOrderAttribute:Attribute{publicintOrder{get;私有集;}publicColumnOrderAttribute(intorder){Order=order;您可以使用反射遍历所有类属性/字段并将其写入CSV的更好方法是定义自定义属性并修饰要导出的成员,并仅导出这些属性。我将我的答案分为两部分:第一部分是如何将一些通用项目列表导出到csv,带有编码和标题-(它只会为指定的标题构建csv数据,并且会忽略不需要的属性)。publicstringExportCsv(IEnumerableitems,Dictionaryheaders){stringresult;使用(TextWritertextWriter=newStreamWriter(myStream,myEncoding)){result=this.WriteDataAsCsvWriter(items,textWriter,headers);}返回结果;}privatestringWriteDataAsCsvWriter(IEnumerableitems,TextWritertextWriter,Dictionaryheaders){//添加空验证////打印列标题StringBuildersb=newStringBuilder();//headersforeach(KeyValuePairkvpinheaders){sb.Append(ToCsv(kvp.Value));sb.Append(",");}sb.Remove(sb.Length-1,1);//最后一个','sb.Append(Environment.NewLine);//thevaluesforeach(variteminitems){try{Dictionaryvalues=GetPropertiesValues(item,headers);foreach(值中的变量值){sb.Append(ToCsv(value.Value));sb.Append(",");}sb.Remove(sb.Length-1,1);//最后一个','sb.Append(Environment.NewLine);}catch(Exceptione1){//做某事}}textWriter.Write(sb.ToString());返回sb.ToString();}//将文本编码为csv的帮助函数:publicstaticstringToCsv(stringinput){if(input!=null){input=input.Replace("rn",string.Empty).Replace("r",string.Empty).Replace("n",string.Empty);如果(input.Contains(""")){input=input.Replace(""","""");}输入=“””+输入+“””;}返回输入;}这是最重要的函数,它从(几乎)任何泛型类中提取属性值privateDictionaryGetPropertiesValues(objectitem,Dictionaryheaders){字典值=newDictionary();if(item==null){返回值;}//我们需要确保每个值都与标题协调,空字符串foreach(varkeyinheaders.Keys){values[key]=String.Empty;}输入t=item.GetType();PropertyInfo[]propertiesInfo=t.GetProperties();foreach(PropertyInfopropertiyInfoinpropertiesInfo){//它并不复杂:字符串、整数、布尔值、枚举if((propertiyInfo.PropertyType.Module.ScopeName=="CommonLanguageRuntimeLibrary")||propertiyInfo.PropertyType.IsEnum){if(headers.ContainsKey(propertiyInfo.Name)){varvalue=propertiyInfo.GetValue(item,null);if(value!=null){values[propertiyInfo.Name]=value.ToString();}}}else//是复杂属性{if(propertiyInfo.GetIndexParameters().Length==0){Dictionarylst=GetPropertiesValues(propertiyInfo.GetValue(item,null),headers);foreach(lst中的var值){如果(!string.IsNullOrEmpty(value.Value)){values[value.Key]=value.Value;}}}}}返回值;}GetPropertiesValues例子:publicMyClass{publicstringName{get;设置;}publicMyEnumType{get;设置;}publicMyClass2Child{get;设置;}}publicMyClass2{publicintAge{get;设置;}公共DateTimeMyDate{get;设置;}}MyClassmyClass=newMyClass(){Name="Bruce",Type=MyEnum.Sometype,Child=newMyClass2(){Age=18,MyDate=DateTime.Now()}};词典标题=新词典();headers.Add("名称","CustomCaption_Name");headers.Add("Type","CustomCaption_Type");headers.Add("年龄","CustomCaption_Age");GetPropertiesValues(myClass,headers));//OUTPUT:{{"Name","Bruce"},{"Type","Sometype"},{"Age","18"}}我的回答基于MichaelKropat的回答我在他的回答中添加了两个函数因为它不想直接写入文件,因为我还有一些进一步的处理要做。相反,我希望标头信息与值分开,以便以后可以将所有内容重新组合在一起。以上就是C#学习教程:CSV通用类(所有属性)的全部内容。如果对你有用,需要进一步了解C#学习教程,希望你多多关注——publicstaticstringToCsvString(Tobj){varfields=frommiintypeof(T).GetMembers(BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static)wherenew[]{MemberTypes.Field,MemberTypes.Property}.Contains(mi.MemberType)让orderAttr=(ColumnOrderAttribute)Attribute.GetCustomAttribute(mi,typeof(ColumnOrderAttribute))选择米;返回QuoteRecord(FormatObject(fields,obj));}publicstaticstringGetCsvHeader(Tobj){varfields=frommiintypeof(T).GetMembers(BindingFlags.Public|BindingFlags.Instance|BindingFlags.Static)wherenew[]{MemberTypes.Field,MemberTypes.Property}.Contains(mi.MemberType)让orderAttr=(ColumnOrderAttribute)Attribute.GetCustomAttribute(mi,typeof(ColumnOrderAttribute))选择mi;返回QuoteRecord(fields.Select(f=>f.Name));}本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处: