C# 非共享操作和NotSupportedException

C# 非共享操作和NotSupportedException,c#,oop,notsupportedexception,C#,Oop,Notsupportedexception,我正在开发一个库来映射Nat设备中的端口。这些Nat设备使用不同的协议(及其版本)来映射端口、获取外部ip地址、查找可用端口、列出它们、释放它们等等 所以,我给他们每人上了一节课: UpnpWanIPConnection1 UpnpWanIPConnection2 UPNPWANPPConnection1 UPNPWANPPConnection2 Pmp 五氯酚 其中每一个都共享一些常见的操作,比如AddPorMapping、GetExternalIP、RemovePortMapping。然

我正在开发一个库来映射Nat设备中的端口。这些Nat设备使用不同的协议(及其版本)来映射端口、获取外部ip地址、查找可用端口、列出它们、释放它们等等

所以,我给他们每人上了一节课:

  • UpnpWanIPConnection1
  • UpnpWanIPConnection2
  • UPNPWANPPConnection1
  • UPNPWANPPConnection2
  • Pmp
  • 五氯酚
其中每一个都共享一些常见的操作,比如AddPorMapping、GetExternalIP、RemovePortMapping。然后,它们在INat中实现了一个接口

该库可按如下方式使用:

var natDevice = NatDiscovery.Discover();  // it returns an INat instance
natDevice.AddPortMapping(100, 100, "tcp");
问题是其中一些包含额外的操作,例如GetAllMappings,而其余的则没有。然后,如果我将这些非共享操作作为接口的一部分,那么那些没有实现该操作的设备(因为它们不属于它们支持的协议的一部分)将需要抛出NotSupportedException,这对使用库的人来说是非常糟糕的。看一看:

var natDevice = NatDiscovery.Discover(); 
try{
   list = natDevice.GetPortList();
}
catch(NotSupportedException)
{
   // sorry, your device donnot support listing
}
我在考虑像CanGetPortList、CanDoThis、CanDoThat这样的房产,但我不喜欢


当前方法(抛出NotsPortedException)是实现这一点的最佳方法吗

您可以尝试为这些特殊情况创建不同的接口,并尝试转换您的类型:

public Interface IPortListGetter
{
   void GetPortList();
}

var natDevice = NatDiscovery.Discover(); 
var portGetter = natDevice as IPortListGetter;
if (portGetter != null)
{  
    portGetter.GetPortList();
}

您可以从您的接口继承到其他接口,因此您将拥有一个核心接口并从中继承奇特的接口,因此您可以为任何类选择最佳接口。

框架中有关于“功能”的先例属性向调用方指示成员将抛出
NotSupportedException

示例:

  • IList.IsReadOnly
    =>如果为false,
    IList.Add()
    和类似命令将抛出

  • DbProviderFactory.CanCreateDataSourceEnumerator


个人在你的情况下,我会添加<代码> can…<代码>属性,但是这是一个主观的决定,你似乎知道你需要考虑的权衡。

查看一些.NET类如何处理类似的问题。例如,Dictionary有一种方法可以解决您在这里遇到的类似情况。为什么不以同样的方式做一些像“TryGetPortList”、“TryDoThis”之类的事情呢?NET程序员很可能已经习惯了这种“尝试”惯例。或者,您将类型用于返回或不返回原语值的方法。这是一个很好的问题,但我认为您会找到一个更好的答案。当然,我知道“功能”属性。但是,它们是正确的还是仅仅是设计不佳的结果?我是说,有一个IReadOnlyList不是更好吗?这就是我的问题,我的设计正确吗?如果是/否,为什么?@Iontivero-所有的设计都是折衷的,所以我认为你不能谈论“正确”或“不正确”。IReadOnlyList是由IList实现的,因此没有说明任何关于功能的内容,只是消费者不希望能够修改列表。增加接口的数量以公开不同的功能也会增加复杂性。我在考虑这些方法,是的,这都是关于权衡的,所以,我将照原样(不支持例外),并将分析功能属性问题,它们在某些场景中是有用的。谢谢。如果一些设备能够doFoo,那么您可以从main继承一个名为Fooable的接口,并为能够doFoo的设备实现Fooable。嗯,不太可能,他没有提到您可以继承接口,这样您就不必在接口中重复声明方法,以防更多接口能够执行相同的操作。如果在所有情况下都支持doFoo方法,那么您可以在核心接口中声明它并将其继承到其他接口中,这样您就不必在所有接口中声明doFoo,因为继承将帮助您。