2014-09-27 36 views
3

我曾希望使用动态类型的对象来写入CSV文件。如何使用CsvHelper编写从DynamicObject派生的类?

我在CsvWriter.WriteObject方法中收到'CsvHelper.CsvWriterException'消息:“没有属性映射为'WpmExport.DynamicEntry'类型。”

这里是我试图使用类:

public class DynamicEntry : DynamicObject 
{ 
    private Dictionary<string, object> dictionary = new Dictionary<string, object>(); 

    public override bool TryGetMember(
     GetMemberBinder binder, out object result) 
    { 
     string name = binder.Name.ToLower(); 
     return dictionary.TryGetValue(name, out result); 
    } 

    public override bool TrySetMember(
     SetMemberBinder binder, object value) 
    { 
     dictionary[binder.Name.ToLower()] = value; 
     return true; 
    } 

    public override IEnumerable<string> GetDynamicMemberNames() 
    { 
     return dictionary.Keys.AsEnumerable(); 
    } 
} 

任何人只要有任何意见或工作的例子吗? http://joshclose.github.io/CsvHelper/的文档提示可能但不提供任何指导。

TIA

回答

3

功能尚不存在。您可以编写dynamic而不是DynamicObject。你可以在这里查看主题的主题。 https://github.com/JoshClose/CsvHelper/issues/187

当功能得到实现,我会更新与它的版本的答案。

更新

这个功能将在3.0可用。您目前可以试用NuGet的3.0-beta。

2

因为我不能等3.0版(和CsvHelper.Excel支持它),我找到了一个临时解决方案。

取类出口:

public partial class EntryReportInventory 
{ 
    public Guid DeviceId { get; set; } 
    [ReportProperty] 
    public string DeviceName { get; set; } 

    public Dictionary<string, object> InventoryValues { get; set; } 

    public EntryReportInventory(Device device, Dictionary<string, object> inventoryValues) 
    { 
     this.DeviceId = device.Id; 
     this.DeviceName = device.Name; 

     this.InventoryValues = inventoryValues; 
    } 
} 

创建映射:

Type genericClass = typeof(DefaultCsvClassMap<>); 
Type constructedClass = genericClass.MakeGenericType(typeof(EntryReportInventory)); 
       return (CsvClassMap)Activator.CreateInstance(constructedClass); 

而现在的魔术。我遍历所有的属性。

foreach (PropertyInfo property in mapping) 
      { 
... 
if (isInventoryReportBaseType && typeof(Dictionary<string, object>).IsAssignableFrom(property.PropertyType)) 
       { 
        var dataSource = (ReportInventoryBase)Activator.CreateInstance(entityType, dbContext); 

        foreach (var item in dataSource.ColumnNameAndText) 
        { 
         var columnName = item.Key; 

         var newMap = new CsvPropertyMap(property); 
         newMap.Name(columnName); 
         newMap.TypeConverter(new InventoryEntryListSpecifiedTypeConverter(item.Key)); 

         customMap.PropertyMaps.Add(newMap); 
        } 
... 
} 

我的转换器:

public class InventoryEntryListSpecifiedTypeConverter : CsvHelper.TypeConversion.ITypeConverter 
    { 
     private string indexKey; 
     public InventoryEntryListSpecifiedTypeConverter(string indexKey) 
     { 
      this.indexKey = indexKey; 
     } 

     public bool CanConvertFrom(Type type) 
     { 
      return true; 
     } 

     public bool CanConvertTo(Type type) 
     { 
      return true; 
     } 

     public object ConvertFromString(TypeConverterOptions options, string text) 
     { 
      throw new NotImplementedException(); 
     } 

     public string ConvertToString(TypeConverterOptions options, object value) 
     { 
      var myValue = value as Dictionary<string, object>; 
      if (value == null || myValue.Count == 0) return null; 

      return myValue[indexKey] + ""; 
     } 
    } 

不知道为什么,但它的作品好几次经过相同的属性。 就是这样:) 你只需要有一个列表(这里:dataSource.ColumnNameAndText,从外部来源填充)来标识列/值。

相关问题