微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

c# – 在不违反类型安全的情况下将不透明对象返回给调用者

我有一个方法应该返回当前状态的快照,另一个方法是恢复该状态.
public class MachineModel
{
    public Snapshot CurrentSnapshot { get; }
    public void RestoreSnapshot (Snapshot saved) { /* etc */ };
}

状态Snapshot类对调用者应该是完全不透明的 – 没有可见的方法属性 – 但是它的属性必须在MachineModel类中可见.我显然可以通过向下转换来实现这一点,即让CurrentSnapshot返回一个对象,并让RestoreSnapshot接受一个对象参数,它将其转换回快照.

但这样的强迫铸造让我觉得很脏.什么是最好的替代设计,允许我既是类型安全的又是不透明的?

更新解决方案:

我结束了接受的答案和关于接口的建议. Snapshot类是一个公共抽象类,在MachineModel中有一个私有实现:

public class MachineModel
{
    public abstract class Snapshot
    {
        protected internal Snapshot() {}
        abstract internal void Restore(MachineModel model);
    }

    private class SnapshotImpl : Snapshot
    {
        /* etc */
    }

    public void Restore(Snapshot state)
    {
        state.Restore(this);
    }
}

由于Snapshot的构造函数方法是内部的,因此程序集外部的调用者将其视为完全不透明且无法从中继承.程序集中的调用者可以调用Snapshot.Restore而不是MachineModel.Restore,但这不是一个大问题.此外,在实践中,您永远无法实现Snapshot.Restore而无法访问MachineModel的私有成员,这应该阻止人们尝试这样做.

解决方法

您可以反转依赖关系并使Snapshot成为MachineModel的子(嵌套类).然后,Snapshot只有一个公共(或内部)Restore()方法,该方法将MachineModel的实例作为参数.由于Snapshot被定义为MachineModel的子级,因此可以看到MachineModel的私有字段.

要恢复状态,下面的示例中有两个选项.您可以调用Snapshot.RestoreState(MachineModel)或MachineModel.Restore(Snapshot)*.

public class MachineModel
{
    public class Snapshot
    {
        int _mmPrivateField;

        public Snapshot(MachineModel mm) 
        { 
            // get mm's state
            _mmPrivateField = mm._privateField;
        }

        public void RestoreState(MachineModel mm) 
        { 
            // restore mm's state
            mm._privateField = _mmPrivateField;
        }
    }

    int _privateField;

    public Snapshot CurrentSnapshot
    {
        get { return new Snapshot(this); }
    }

    public void RestoreState(Snapshot ss)
    {
        ss.Restore(this);
    }
}

例:

MachineModel mm1 = new MachineModel();
    MachineModel.Snapshot ss = mm1.CurrentSnapshot;
    MachineModel mm2 = new MachineModel();
    mm2.RestoreState(ss);

*将Snapshot.RestoreState()作为内部并将所有调用者放在程序集之外是最简洁的,因此执行还原的唯一方法是通过MachineModel.RestoreState().但是你在Jon的回答中提到在同一个程序集中会有调用者,所以没有多大意义.

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。

相关推荐