Skip to content

Instantly share code, notes, and snippets.

@akimboyko
Last active December 15, 2015 23:09
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save akimboyko/5338320 to your computer and use it in GitHub Desktop.
Save akimboyko/5338320 to your computer and use it in GitHub Desktop.
Ninject Convention-over-configuration: find all implementations of interface in assembly and bind them by name Answer to http://stackoverflow.com/questions/15868820/ninject-conventions-with-ninject-factory-extension-to-bind-multiple-types-to-one
void Main()
{
using(var kernel = new StandardKernel(new CarModule()))
{
kernel.Load<FuncModule>(); // for sake of LinqPAD
var factory = kernel.Get<ICarFactory>();
Assert.That(factory, Is.Not.Null);
var mercedes = factory.CreateCar("Mercedes");
var ferrari = factory.CreateCar("Ferrari");
Assert.That(mercedes, Is.Not.Null.And.InstanceOfType(typeof(Mercedes)));
Assert.That(ferrari, Is.Not.Null.And.InstanceOfType(typeof(Ferrari)));
mercedes.Drive();
mercedes.Stop();
ferrari.Drive();
ferrari.Stop();
}
}
#region ICar implementations
public interface ICar
{
void Drive();
void Stop();
}
public class Mercedes : ICar
{
public void Drive()
{
"Do mercedes drive stuff...".Dump();
}
public void Stop()
{
"Do mercedes stop stuff... ".Dump();
}
}
public class Ferrari : ICar
{
public void Drive()
{
"Do ferrari drive stuff...".Dump();
}
public void Stop()
{
"Do ferrari stop stuff... ".Dump();
}
}
#endregion
public interface ICarFactory
{
ICar CreateCar(string carType);
}
public class CarModule : NinjectModule
{
public override void Load()
{
Bind<ICarFactory>()
.ToFactory(() => new UseFirstArgumentAsNameInstanceProvider());
Kernel.Bind(scanner => scanner
.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<ICar>()
.BindWith(new BaseTypeBindingGenerator<ICar>()));
}
}
public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(System.Reflection.MethodInfo methodInfo, object[] arguments)
{
return (string)arguments[0];
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
{
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
public class BaseTypeBindingGenerator<InterfaceType> : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
if (type != null && !type.IsAbstract && type.IsClass && typeof(InterfaceType).IsAssignableFrom(type))
{
string.Format("Binds '{0}' to '{1}' as '{2}", type, type.Name, typeof(InterfaceType)).Dump();
yield return bindingRoot.Bind(typeof(InterfaceType))
.To(type)
.Named(type.Name) as IBindingWhenInNamedWithOrOnSyntax<object>;
}
}
}
@Lumirris
Copy link

Lumirris commented Apr 8, 2013

This works great! Is the .Dump() extension left over from LinqPAD or do you use something like that for development in VisualStudio?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment