Question

I'm developing a library to map ports in Nat devices. These Nat devices use different protocols (and their versions) to map ports, get the external ip address, find available ports, list them, release them, etc.

So, I have one class for each of them:

  • UpnpWanIPConnection1
  • UpnpWanIPConnection2
  • UpnpWanPPPConnection1
  • UpnpWanPPPConnection2
  • Pmp
  • Pcp

Each of those share a few common operations like AddPorMapping, GetExternalIP, RemovePortMapping then, they implement an interface INat.

The library can be used as follow:

var natDevice = NatDiscovery.Discover();  // it returns an INat instance
natDevice.AddPortMapping(100, 100, "tcp");

The problem is some of them includes extra operations, eg. GetAllMappings while the rest don't. Then, if I include those non-shared operations as part of the interface, those devices that don't implement the operation (because is not part of the protocol that they support) will require to throw a NotSupportedException and that is very bad for who uses the library. Take a look:

var natDevice = NatDiscovery.Discover(); 
try{
   list = natDevice.GetPortList();
}
catch(NotSupportedException)
{
   // sorry, your device donnot support listing
}

I was thinking about properties like CanGetPortList, CanDoThis, CanDoThat but I don't like it.

Is the current approach (throwing NotSpportedException) the best way to do this?

Was it helpful?

Solution

There are precedents in the Framework for "capability" properties to indicate to callers that members will throw a NotSupportedException.

Examples:

  • IList<T>.IsReadOnly => if false, IList<T>.Add() and similar will throw

  • DbProviderFactory.CanCreateDataSourceEnumerator

Personally in your situation I would add the Can... properties, but it's a subjective decision and you seem to be aware of the trade-offs you need to consider.

OTHER TIPS

You can try creating different Interfaces for those special cases, and try casting your type:

public Interface IPortListGetter
{
   void GetPortList();
}

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

You can inherit from your interface to other interfaces, so you would have a core interface and inherit fancy interfaces from that, so you can choose your optimal interface for any class.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top