A case where interface versioning works
In some situations, interface versioning is not a problem. I'll expose a scenario in order to show you a case where it works fine and it's simple.
Here is the scenario: we have an application that uses plug-ins. The plug-ins, when loaded by the application, use an interface the application hands to them.
Let's call the interface IHost.
Step 1
When the application is created, a first plug-in is
written. This plug-in (Plugin1) is then using the only
method of the IHost interface.
The IHost interface is
defined in an assembly we name Interfaces.
namespace Interfaces { public interface IHost { void Method1(); } }
The Plugin1 class using the IHost interface is defined in an assembly named Plugin1. The Plugin1 assembly references the Interfaces assembly.
namespace Plugins { public class Plugin1 { static public void Calcul(Interfaces.IHost host) { host.Method1(); } } }
Step 2
The application uses the Plugin1 class, handing it an
object implementing the IHost interface.
The
application references the Interfaces and Plugin1
assemblies.
class Host : Interfaces.IHost { public void Method1() { Console.WriteLine("Host.Method1"); } }
...
Interfaces.IHost host = new Host(); Plugins.Plugin1.Load(host);
Step 3
The IHost is enriched with a new method. A new version of the Interfaces assembly is generated.
namespace Interfaces { public interface IHost { void Method1(); void Method2(); } }
A new plugin named Plugin2 using the new version of the IHost interface is created.
The Plugin2 assembly references the Interfaces assembly.
namespace Plugins { public class Plugin2 { static public void Calcul(Interfaces.IHost host) { host.Method1(); host.Method2(); } } }
Step 4
The application is updated to load Plugin2 as well as
Plugin1. The object implementing the IHost interface must
implement the new method.
The application then
references Interfaces, Plugin1, Plugin2.
The Plugin1 assembly is not recompiled.
In Visual Studio, you can for example remove the Plugin1
project from the solution.
class Host : Interfaces.IHost { public void Method1() { Console.WriteLine("Host.Method1"); }
public void Method2() { Console.WriteLine("Host.Method2"); } }
...
Interfaces.IHost host = new Host(); Plugins.Plugin1.Load(host); Plugins.Plugin2.Load(host);
Conclusion
We managed to use different versions of an interface, without having to recompile the code that uses previous versions of this interface. The name of the interface has not changed (no IHost2 or IHostEx…).
Final notes
-
This works because the interface is in its own
assembly. This would not work if the interface was
compiled within the Plugin1 and Plugin2 assemblies. Each
plug-in sees the IHost interface as it was when it was
compiled.
Plugin1 only uses Method1, Plugin2 can use both Method1 and Method2. - Of course, this only works if we add things to the interface. If we remove Method1 in the new version, we'd get a MissingMethodException when Plugin1 is loaded.
- The compiler generates a warning stating that the first version of the Interfaces assembly is ignored and that the latest version is used. This is exactly what we want.
- Instead of statically referencing the plug-ins' assemblies, the application could load them dynamically. In this case, there would be no warning.
