C# 如何使用getter-only接口以良好的方式处理接口的内部实现?
在C# 如何使用getter-only接口以良好的方式处理接口的内部实现?,c#,interface,C#,Interface,在合同项目中,我定义了一些接口,例如 public interface IProject : INotifyPropertyChanged { string Path { get; } } 通过引用合同程序集,该接口可暴露于各种前端(例如WPF、命令行等)。 它只公开了Path的getter,因为任何用户都不能修改它。每次修改都发生在运行时程序集中 执行所有繁重工作的运行时项目实现了am内部项目,当然需要某种类型的路径设置器(属性、构造函数等) 运行时创建一个项目,但向用户返回一个i项
合同
项目中,我定义了一些接口,例如
public interface IProject : INotifyPropertyChanged
{
string Path { get; }
}
通过引用合同
程序集,该接口可暴露于各种前端(例如WPF、命令行等)。
它只公开了Path的getter,因为任何用户都不能修改它。每次修改都发生在运行时
程序集中
执行所有繁重工作的运行时项目实现了am内部项目
,当然需要某种类型的路径设置器(属性、构造函数等)
运行时
创建一个项目
,但向用户返回一个i项目
,以满足合同要求
当用户对i项目执行操作时,例如
runtime.SetPath(iProjectObject, "my new path");
从传递给设置路径的接口获取有效的项目
的正确方法是什么
铸造(因此)是一条路吗?
在我看来,定义好的合同,然后四处转转似乎有点肮脏。
但是,可以假定,IProject
始终是Project
,因为它仅由运行时
程序集创建和管理。但我不能保证用户不会从IProject
派生并将其提供给我的运行时
像runtime
这样具有IProject
到Project
引用的映射的非强制转换选项看起来很奇怪,因为它们基本上指向同一个对象
因此,每个处理i项目的公共runtime
方法都需要用于转换、假设、抛出错误类型等的样板文件,如果您的使用者(runtime.SetPath)是需要一个项目实例,而不仅仅是iProject的实现,那么SetPath实际上并不符合iProject接口契约,因为它需要一个cast来处理iProjectObject,而不是将其视为iProject
这听起来像是一个抽象项目类的好例子,该类执行满足运行时所需的最小项目相关实现,同时还允许用户子类化。这也将消除boilerplate unboxing/trycast内容。使用标记接口,使其在运行时程序集中内部,并让您的服务从IProject和标记接口继承。当运行时获取IProject实例时,检查它是否也是mark接口的类型
运行时程序集中的代码如下所示:
internal interface IProjectTag{};
internal class ProjectService: IProject,IProjectTag{
public void SetPath
{
if (this is IProjectTag)
{...}
}
}
为什么不简单地在IProject
中提供所需的附加信息,而不是尝试回溯到底层类型?另外,除非您是用结构而不是类实现接口,否则这不是取消装箱,它只是强制转换。@Servy,关于取消装箱,您是对的IProject本身没有逻辑,因为运行时在后台执行多线程、调度、资源处理和共享等操作。在每个IProject
实例中执行此操作将非常复杂,因为有大量IProject
实例需要同步。这也将打破单一责任原则,因为i项目基本上只是一个结果处理。虽然运行时
在做任何事情方面都不是单一的,但它仍然为所有项目管理一个公共上下文
感谢您的输入。你和@Servy指出了一个重要的事实。我定义了一个接口,然后开始解决它。从设计角度来看,没有理由将IProject创建为普通属性容器,并为其上的操作提供另一个类。简单的IProject对象基本上是我实验过的基于流的设计的遗留物,其中“消息”在操作之间流动,其中一个就是IProject。我会重新设计整件事。再次感谢。感谢Matt,虽然这将解决手头的问题,但它看起来像是一种补偿我将IProject视为普通数据容器的错误设计决策的方法。其他的评论和回答让我修改了这个概念,以避免这种“无上下文”的对象。