如何在以下界面中的Invoke
方法上放置前提条件,说明ObjectId
表示的对象必须存在?:
interface IDeleteObjectCommand {
Guid ObjectId { get; }
void Invoke();
}
尝试#1
我已经有一个名为IObjectExistsCommand
的命令,可用于确定对象是否存在。这些命令可以通过IObjectExistsCommandFactory
实例化。我已经考虑过执行以下操作,但这会给命令的界面(IMO)增加不良噪音:
interface IDeleteObjectCommand {
IObjectExistsCommandFactory ObjectExistsCommandFactory { get; }
Guid ObjectId { get; }
// Contract.Requires(ObjectExistsCommandFactory.Create(ObjectId).Invoke());
void Invoke();
}
尝试#2
与上述类似,但使用ServiceLocator
除外。由于显而易见的原因而不受欢迎,但更清洁:
interface IDeleteObjectCommand {
Guid ObjectId { get; }
// Contract.Requires(ServiceLocator.Get<ObjectExistsCommandFactory>().Create(ObjectId).Invoke());
void Invoke();
}
编辑:同样,您如何定义外部状态的后置条件?即说这种方法会导致存在新文件。
答案 0 :(得分:1)
我认为这是一个坏主意。这是受竞争条件限制的合同之一,我不喜欢这些(两个来电者确认合同满足,然后一个人赢得比赛以删除对象,然后第二个获得合同违规例外它试图删除对象。)
如果要删除的对象不存在,则抛出异常。
答案 1 :(得分:0)
我决定创建一个'Preconditions'enum
来定义外在的前提条件。然后我在接口上定义了一个返回enum
的单独方法,从而暗示外部状态的哪些位无效:
interface IDeleteObjectCommand {
Guid ObjectId { get; }
DeleteObjectPreconditions? GetImpediments();
// Contract.Requires(!this.GetImpediments().HasValue);
void Invoke();
}
enum DeleteObjectPreconditions { ObjectExists, ObjectUnlocked };
我这样做完全疯了吗?当然,唯一的缺点是用户没有可靠的手段来满足前提条件......
编辑:我实际上更喜欢这种服务定位方法。至少通过这种方法,用户能够证明通过签约(尽管是服务定位)界面满足前提条件。
编辑2:这提出了一个有趣的问题......你如何定义外在状态的后置条件?