在contract
项目中,我定义了一些界面,例如
public interface IProject : INotifyPropertyChanged
{
string Path { get; }
}
通过引用contracts
程序集,接口暴露于各种前端(例如WPF,命令行等)。
它只暴露Path的getter,因为没有用户应该能够修改if。每次修改都发生在runtime
程序集中。
runtime
项目,它执行所有繁重的工作工具internal
Project
,当然需要Path
(属性,ctor等)的某种设置器。 )
runtime
创建Project
但向用户返回IProject
以满足合同。
当用户对IProject
执行操作时,例如
runtime.SetPath(iProjectObject, "my new path");
从传递给Project
的界面获取有效SetPath
的正确方法是什么?
是否可以投射(因此unboxing)?
在某种程度上,我似乎很肮脏地定义好的合同,然后转发。
但是,可以假设IProject
始终为Project
,因为它仅由runtime
程序集创建和管理。但我无法保证用户不会从IProject
派生并将其提供给我的runtime
。
具有runtime
到IProject
引用地图的Project
等非投放替代品似乎很奇怪,因为它们基本上指向同一个对象。
因此,处理runtime
的每个公共IProject
方法都需要样板来进行投射,假设,投掷错误类型等?
答案 0 :(得分:1)
从设计角度来看,如果您的使用者(runtime.SetPath)需要一个Project实例而不仅仅是iProject的实现,那么SetPath实际上并不符合iProject接口契约的开头,因为它需要一个强制转换来执行任何操作对iProjectObject很有用,而不是将其视为iProject。
这听起来像是一个抽象的Project类的好例子,它完成了满足运行时所需的最小Project相关实现,同时也允许用户进行子类化。这样就可以消除boilierplate拆箱/尝试播放的东西。
答案 1 :(得分:0)
使用标记接口,并使其在运行时程序集中内部,并让您的服务继承从IProject和mark接口。当运行时获取IProject实例时,检查它是否也是标记接口的类型。
代码在运行时程序集中会这样:
internal interface IProjectTag{};
internal class ProjectService: IProject,IProjectTag{
public void SetPath
{
if (this is IProjectTag)
{...}
}
}