You asked for it, so i'm going to give you this really smelly, ugly code ;-)
using System;
using System.Collections.Generic;
using FluentAssertions;
using Ninject;
using Ninject.Extensions.Conventions;
using Ninject.Extensions.Conventions.BindingGenerators;
using Ninject.Syntax;
using Xunit;
public class MultiBaseBindingGenerator : IBindingGenerator
{
public IEnumerable<IBindingWhenInNamedWithOrOnSyntax<object>> CreateBindings(Type type, IBindingRoot bindingRoot)
{
for (int i = 0; i < 10; i++)
{
yield return bindingRoot.Bind(type.BaseType).To(type);
}
}
}
public abstract class Foo
{
}
public class SomeFoo : Foo
{
}
public class SomeFooUser
{
public IEnumerable<Foo> Foos { get; set; }
public SomeFooUser(IEnumerable<Foo> foos)
{
this.Foos = foos;
}
}
public class Demo
{
[Fact]
public void FactMethodName()
{
var kernel = new StandardKernel();
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFrom<Foo>()
.BindWith<MultiBaseBindingGenerator>());
kernel.Get<SomeFooUser>().Foos.Should().HaveCount(10);
}
}
This will create 10 instances of Foo every time you inject an IEnumerable<Foo>
. You could make the instance count configurable by putting an attribute on the type and reading it @ IBindingGenerator
. However, configuration can only be read when or before creating the bindings.
There are several other possibilities to reach the same goal. I would suggest creating only one binding - as you are doing now. Create a factory `IEnumerable CreateMultipleAsConfigured()' which creates as many instances as required.
Another possibility would be to create your own collection type:
public class MultipleAsConfigured<T> : Collection<T> { }
and bind it using a provider:
IBindingRoot.Bind(typeof(MultipleAsConfigured<>).ToProvider(typeof(MultipleAsConfiguredProvider));
and have the provider read the configuration, instanciate as many objects as required (using IContext.Get()), creating the MultipleAsConfigured, and adding the items...