我有两个接口IImporter和IExporter一个处理这些接口实例的类:
class IoManager
{
public ReadOnlyCollection<IImporter> Importers { get; }
public ReadOnlyCollection<IExporter> Exporters { get; }
// ...
}
Run Code Online (Sandbox Code Playgroud)
在这个类中,我想实现一个Add(...)可以添加导入器或导出器的方法.
我知道我可以为两个接口创建一个重载
public void Add(IExporter exporter);
public void Add(IImporter importer);
Run Code Online (Sandbox Code Playgroud)
问题是如果我想添加一个实现两个接口的对象,比如CsvIo : IImporter, IExporter通过Add(...)函数,我得到一个不明确的调用编译错误,因为CsvIo两个重载都接受了.
IExporter,IImporter或两者兼而有之.Add(...)调用中强制转换类型Add((IImporter) CsvIoInstance),因为这表明只使用了这种类型的导入器.但是两个重载都检查对象是否实现了两个接口并相应地将它添加到两个列表中.有没有办法以连贯的方式接受不同的类型(这样每个类型的调用看起来都一样)?
澄清我的实现:这是插件系统的一部分.我想添加多种方式来存储我的数据(以便其他应用程序可以使用它).该IExporter接口用于在IImporter接口加载数据时存储数据.该IoManager管理所有注册的插件.当然,一个类可以(并且可能是常见的)实现某种文件格式的导出和导入.这就是为什么我希望Add(...)函数在所有情况下都相似.
但是,再次考虑它(如评论中已经说明的那样)插件只在运行时才知道,这使得模糊性成为我认为的过时问题.所以这只适用于内置类型.
我想特别关注一句话:
我不想在
Add(...)调用中强制转换类型Add((IImporter) CsvIoInstance),因为这表明只使用了这种类型的导入器.但是两个重载都检查对象是否实现了两个接口并相应地将它添加到两个列表中.
您当前的设计已经放弃了类型安全的目标之一:避免运行时类型检查.理想情况下,采用IImporter参数的方法应该只使用该参数IImporter.这在方法的调用者和实现者之间形成了一种"契约":实现者相信调用者将提供它所需要的东西,并且调用者相信实现者只会以这种方式使用它.(另见:最不惊讶的原则.)
想象一下,你是这个班的消费者.有IImporters签名的集合和方法Add(IImporter foo).你期望这种方法做什么? 我希望它添加foo到列表中IImporters- 我不希望它也做其他事情,因为我的对象碰巧实现了另一个接口(例如IExporter).以这种方式使用类型系统"背叛"您与调用者建立的合同.
将方法名称更改为AddImporter和AddExporter,然后让每个方法仅将参数添加到相应的列表中.这解决了重载解析的问题,并且意味着调用者正在获得他们所要求的内容.
| 归档时间: |
|
| 查看次数: |
146 次 |
| 最近记录: |