ASP.NET Hosting

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.

App+plugin

Let's call the interface IHost.

App+plugin+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.

No Comments