I've got something like this:
// This gets implemented by plugin authors to get callbacks about various things.
public interface ExternalPlugin
{
// This gets called by the main application to tell the plugin some data
// is available or similar.
void DoStuff(SomeDataBlob blob);
}
// Data blob for v1 of API
public class SomeDataBlob
{
internal SomeDataBlob(string prop) { Prop = prop; }
// Some piece of data that V1 plugins need
public string Prop { get; private set; }
}
// FUTURE!
// Data blob API v2 of API
public class SomeDataBlobV2 : SomeDataBlob
{
// Can be passed to clients expecting SomeDataBlob no problem.
internal SomeDataBlobV2(string prop, string prop2) :base(prop) { Prop2 = prop2; }
// Some piece of data that V2 plugins need. V2 plugins can cast to this from
// SomeDataBlob, but still can load successfully into older versions that support
// only V1 of the API
public string Prop2 { get; private set; }
}
I have to make SomeDataBlob
public so that it can be used as a member of the public interface method ExternalPlugin.DoStuff
. However, I would not like to allow clients to inherit from that class and thus be susceptible to the brittle base class problem. (All derivatives of that class should be kept in the same assembly)
Marking the class sealed
goes too far because I believe removing sealed
is a breaking API change; and even if that isn't, once I ship SomeDataBlobV2
clients could still do the wrong thing and inherit from SomeDataBlob
directly.
Is there a way to enforce this kind of pattern?