Imagine I have the following classes and interfaces:
public interface IService { }
public class DefaultService : IService { }
public
I've been working on something similar recently and came up with somewhat simpler solution of your problem (although a bit weaker).
What should suffice is to bind a generic implementation (DefaultService) to the generic interface, and concrete implementations (FooService, BarService) to the concrete interfaces. When you ask for a concrete instance of the interface, Ninject resolves whether you defined the concrete binding. If you did, it gives you the appropriate instance, otherwise it falls through to the generic binding. The following code should do the trick.
var kernel = new StandardKernel();
kernel.Bind(typeof(IService<>)).To(typeof(DefaultService<>));
kernel.Bind>().To();
kernel.Bind>().To();
EDIT:
The concept works throughout the whole Ninject, so you can use it along with Extensions.Conventions as well. e.g. define the following:
public class Foo{}
public class Bar{}
public class Dog{}
public interface IService{}
public class DefaultService : IService{}
public class FooService : IService{}
public class BarService : IService{}
use conventions to bind the services:
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom(typeof(IService<>))
.BindSingleInterface());
and create and check the appropriate services:
Assert.IsInstanceOf(kernel.Get>());
Assert.IsInstanceOf(kernel.Get>());
Assert.IsInstanceOf>(kernel.Get>());