I'm using the Ninject Factory extension. Is it possible to make the ConstructorArguments that are created automatically to have inherit = true? I would like the following to work:
kernel.Bind<IFactory>.ToFactory();
where IFactory is:
public interface IFactory {
View GetView(object param);
}
and param is submitted to View:s dependencies (View will not need it).
I know I can just implement the factory myself, but I was wondering if the Factory Extension had any (undocumented) support for it out of the box?
No, this is not supported out of the box. There's just two things it can do out of the box:
IFactory
method name starts with Get
)What you could do is write your own customized IInstanceProvider
.
See this answer which describes how to apply your custom IInstanceProvider
.
The IInstanceProvider
is the place where you would put such (customized) stuff.
What we did was write a generic instance provider which performs some reflection to detect several custom attributes which were then interpreted to allow several things (inheriting, inject when name matches, inject when type matches, constrained resolution, determine which type will be instantiated, add a parameter to the request,...)
However, for a single application (not as in one piece of software, but rather in one piece of code using it) it's probably not worth it. I'd just implement the factory yourself.
IInstanceProvider
with inherited ConstructorArgument
public class InheritingConstructorArgumentsInstanceProvider : StandardInstanceProvider
{
protected override IConstructorArgument[] GetConstructorArguments(
MethodInfo methodInfo,
object[] arguments)
{
return methodInfo
.GetParameters()
.Select((parameter, index) =>
new ConstructorArgument(
parameter.Name,
arguments[index],
true))
.Cast<IConstructorArgument>()
.ToArray();
}
}
which is then bound like this:
kernel
.Bind<IFactory>()
.ToFactory(() => new InheritingConstructorArgumentsInstanceProvider());
here's the complete code:
namespace NinjectTest.CustomFactory
{
using System.Linq;
using System.Reflection;
using FluentAssertions;
using Ninject;
using Ninject.Extensions.Factory;
using Ninject.Parameters;
using Xunit;
public class InheritingConstructorArgumentsInstanceProvider : StandardInstanceProvider
{
protected override IConstructorArgument[] GetConstructorArguments(
MethodInfo methodInfo,
object[] arguments)
{
return methodInfo
.GetParameters()
.Select((parameter, index) =>
new ConstructorArgument(
parameter.Name,
arguments[index],
true))
.Cast<IConstructorArgument>()
.ToArray();
}
}
public class Foo
{
public Bar Bar { get; private set; }
public Foo(Bar bar)
{
Bar = bar;
}
}
public class Bar
{
public string Id { get; private set; }
public Bar(string id)
{
Id = id;
}
}
public interface IFactory
{
Foo Create(string id);
}
public class Test
{
[Fact]
public void Foo()
{
var kernel = new StandardKernel();
kernel
.Bind<IFactory>()
.ToFactory(() => new InheritingConstructorArgumentsInstanceProvider());
const string expectedId = "Hello You!";
kernel.Get<IFactory>().Create(expectedId).Bar.Id.Should().Be(expectedId);
}
}
}