这个字段怎么是空的

本文关键字:字段 | 更新日期: 2023-09-27 18:27:21

我得到一个null异常,但字段被初始化为空列表。那么它怎么可能是空的呢?

错误出现在此方法的第二行(在_hydratedProperties上):

protected virtual void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
{
    string propertyName = GetPropertyName(expression);
    if (!this._hydratedProperties.Contains(propertyName)) { this._hydratedProperties.Add(propertyName); }
}

这就是字段的声明方式:

public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    private List<string> _hydratedProperties = new List<string>();

这就是它的设置:

    public Eta Eta
    {
        get { return this._eta; }
        set
        {
            this._eta = value;
            NotifyPropertyChanged(() => this.Eta);
        }
    }

这是完整的类别(删除了注释和非相关部分):

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    private List<string> _hydratedProperties = new List<string>();
    public bool IsPropertyHydrated(string propertyName)
    {
        return this._hydratedProperties.Contains(propertyName);
    }
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void NotifyPropertyChanged<T>(Expression<Func<T>> expression)
    {
        string propertyName = GetPropertyName(expression);
        if (!this._hydratedProperties.Contains(propertyName)) { this._hydratedProperties.Add(propertyName); }
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
    public string GetPropertyName<T>(Expression<Func<T>> expression)
    {
        MemberExpression memberExpression = (MemberExpression)expression.Body;
        return memberExpression.Member.Name;
    }
}

派生类:

[DataContract]
public class Bin : EntityBase<Bin>
{
    private Eta _eta;
    [DataMember]
    public Eta Eta
    {
        get { return this._eta; }
        set
        {
            this._eta = value;
            NotifyPropertyChanged(() => this.Eta);
        }
    }
}

这个字段怎么是空的

以下是线索:

[DataContract]

是的。DataContractSerializer不调用任何构造函数。相反,它使用FormatterServices.GetUninitializedObject来创建将被反序列化的对象。这将绕过构造函数调用。

您的初始值设定项:

private List<string> _hydratedProperties = new List<string>();

由编译器转换为隐式默认构造函数。

作为一种变通方法,您可以使用带有OnDeserializingAttribute:的反序列化回调

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged
    where TSubclass : class
{
    private List<string> _hydratedProperties;
    protected EntityBase()
    {
        Init();
    }
    private void Init()
    {
        _hydratedProperties = new List<string>()
    }
    [OnDeserializing]
    private void OnDeserializing(StreamingContext context)
    {
        Init();
    }
    // ... rest of code here
}

我找到了一个比Lucas提供的更简单的答案。我不确定这个是否真的更好,但它很简单,而且很有效。我所做的只是将DataMember属性添加到字段中。由于这指定字段是数据协定的一部分,因此它包含在序列化/反序列化中,不再导致null引用错误。

[DataContract]
public abstract class EntityBase<TSubclass> : INotifyPropertyChanged where TSubclass : class
{
    [DataMember]
    private List<string> _hydratedProperties = new List<string>();
    // More code here
}