【问题标题】:FileHelpers interprets event handlers as fieldsFileHelpers 将事件处理程序解释为字段
【发布时间】:2015-05-11 10:16:30
【问题描述】:

我有一个从 Web 服务中使用的类,我尝试使用 FileHelpers 库将其导出到 csv。但是,该类有一个 PropertyChangedEventHandler,引擎将其作为字段读取,因此我收到以下异常

{“类型:PropertyChangedEventHandler的字段:'PropertyChanged'是 非系统类型,因此该字段需要 CustomConverter(请参阅文档 了解更多信息)。”}

我尝试添加 FieldIgnored 属性,但编译器错误提示该属性仅在字段声明中有效

有没有办法让引擎忽略事件处理程序?还是我必须将 Web 服务调用的结果转换成一个全新的(都是相同的类)?

任何想法

【问题讨论】:

    标签: c# filehelpers


    【解决方案1】:

    您的问题是由于 C# 自动实现 event 的方式以及您用于专门检测这种情况并提供更有用的错误消息的库出现故障而发生的。

    特别是,当你声明这个时:

    public event PropertyChangedEventHandler PropertyChanged;
    

    你在课堂上真正得到的是这样的:

    private PropertyChangedEventHandler PropertyChanged;
    
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { PropertyChanged += value; }
        remove { PropertyChanged -= value; }
    }
    

    多年来,addremove 方法的确切实现发生了变化。实际上,以上只是示例……编译器从未真正实现过这样的事件。重要的是你得到both 一个事件和一个字段,具有相同的名称。图书馆正在寻找该领域并抱怨它。

    您应该能够通过自己明确实施事件来解决此问题。例如:

    [FieldIgnored]
    private PropertyChangedEventHandler PropertyChangedField;
    
    public event PropertyChangedEventHandler PropertyChanged
    {
        add { PropertyChanged += value; }
        remove { PropertyChanged -= value; }
    }
    

    只要您不需要 addremove 方法是线程安全的,这将正常工作。但是,请注意,C# 编译器确实将事件 addremove 方法实现为线程安全的;如果你想遵循 C# 编译器的模式,你会想要这样的:

    [FieldIgnored]
    private PropertyChangedEventHandler PropertyChangedField;
    
    public event PropertyChangedEventHandler PropertyChanged
    {
        add
        {
            PropertyChangedEventHandler eventHandler = this.PropertyChangedField;
            PropertyChangedEventHandler comparand;
            do
            {
                comparand = eventHandler;
                eventHandler = Interlocked.CompareExchange<PropertyChangedEventHandler>(
                    ref this.PropertyChangedField,
                    (PropertyChangedEventHandler) Delegate.Combine(
                        (Delegate) comparand, (Delegate) value),
                    comparand);
            } while (eventHandler != comparand);
        }
    
        remove
        {
            PropertyChangedEventHandler eventHandler = this.PropertyChangedField;
            PropertyChangedEventHandler comparand;
            do
            {
                comparand = eventHandler;
                eventHandler = Interlocked.CompareExchange<PropertyChangedEventHandler>(
                    ref this.PropertyChangedField,
                    (PropertyChangedEventHandler) Delegate.Remove(
                        (Delegate) comparand, (Delegate) value),
                    comparand);
            } while (eventHandler != comparand);
        }
    }
    

    【讨论】:

    • 感谢彼得,但是该事件已经在 Web 服务类中的自动生成代码中实现,我不想触及。我可以通过在我可以编辑的部分类上使用元数据来将属性添加到字段中。但是我无法按照您的建议重新实现该事件。当事件在自动生成的代码中时,我该怎么做?
    • 原始问题中没有提及自动生成或部分类。坦率地说,您的问题中没有足够的上下文来理解您为什么以及如何将这个 Web 服务类与 FileHelpers 库一起使用。但是鉴于目前提供的信息,听起来您唯一可行的选择是使用适配器类;即不要将 Web 服务类提供给 FileHelpers 库,而是声明一个专门用于文件 I/O 方面的新类,该类包含或从 Web 服务实例初始化。
    • 对不起,我有点匆忙写了原始问题。您几乎已经证实了我的怀疑,所以感谢您的帮助
    【解决方案2】:

    FileHelpers 类只是一种使用有限的 C# 语法作为定义语言来定义平面文件规范的方法。因此,FileHelpers 类是一种不常见的类型,您不应尝试以任何其他方式使用它。

    或者我是否必须转换 Web 服务调用的结果 进入一个全新的(都是相同的类)?

    是的!这是推荐的方法。仅将 FileHelpers 类视为 CSV 格式的“规范”。这应该是它的唯一作用。

    如果您需要更“正常”对象中的记录(在您的情况下,您的 Web 服务类与事件),然后在导入后映射结果。这可以通过以下方式轻松完成:

    FileHelperEngine engine = new FileHelperEngine<FileHelpersOrder>(); 
    var records = engine.ReadFile("FileIn.txt");
    
    var niceOrders = records.Select(
        x => new NiceOrder() 
           { Number = x.Number,  
             Customer = x.Customer 
             // etc.
           });
    

    FileHelpersOrder 是您的 CSV 规范,NiceOrder 类是您的 Web 服务类,适当的 OOP 类具有必要的属性、方法等。

    (注意:这允许 CSV 格式与目标对象有很大不同。想象一下,例如,您要从具有数十个格式的列中导入一小部分列。这种方法可以让您保持独立)。

    如果要导出,则需要执行相反的操作,,从NiceOrder 的集合中选择FileHelpersOrder 的集合。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-11-07
      • 2013-12-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-11-27
      • 2018-01-25
      相关资源
      最近更新 更多