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视为普通数据容器的错误设计决策的方法。其他的评论和回答让我修改了这个概念,以避免这种“无上下文”的对象。