1、创建深度拷贝扩展类

public static class ObjectCloneExtension
{
    public static T DeepClone<T>(this T value)
    {
        using (var ms = new MemoryStream())
        {
            var formatter = new BinaryFormatter();
            formatter.Serialize(ms, value);
            ms.Position = 0;

            return (T)formatter.Deserialize(ms);
        }
    }
}

2、添加需要拷贝的实体对象,实现INotifyPropertyChanged接口

[Serializable]
public class BaseViewModel : INotifyPropertyChanged
{
    [NonSerialized]
    private Control _control;

    public Control Control
    {
        get { return _control; }
        set { _control = value; }
    }

    protected bool OffLine { get; set; }

    public virtual void OnSelectModule(string moduleName) { }

    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

3、调用

public void Clone()
{
    var model = new BaseViewModel
    {
        Control = this.Control
    };
    var clone = model.DeepClone();
}

4、调用时报System.ComponentModel.ReflectPropertyDescriptor未标记为可序列化异常

5、PropertyChanged添加[NonSerialized]会编译异常,需要添加[field: NonSerialized],修改之后的实体对象如下

[Serializable]
public class BaseViewModel : INotifyPropertyChanged
{
    [NonSerialized]
    private Control _control;

    public Control Control
    {
        get { return _control; }
        set { _control = value; }
    }

    protected bool OffLine { get; set; }

    public virtual void OnSelectModule(string moduleName) { }

    [field: NonSerialized]
    public event PropertyChangedEventHandler PropertyChanged;

    [NotifyPropertyChangedInvocator]
    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(propertyName));
        }
    }
}

6、再次调用就正常了

结论:对于实体的事件字段,不能使用[NonSerialized],需要使用[field: NonSerialized]