从工厂继承ConstructorParameter
本文关键字:ConstructorParameter 继承 工厂 | 更新日期: 2023-09-27 18:09:09
我正在使用Ninject Factory扩展。是否有可能使自动创建的ConstructorArguments具有inherit = true?我希望下面的代码能起作用:
kernel.Bind<IFactory>.ToFactory();
public interface IFactory {
View GetView(object param);
}
和参数被提交给View:s的依赖项(View不需要它)。
我知道我可以自己实现工厂,但我想知道工厂扩展是否有任何(未记录的)开箱即用的支持?
不,这是不支持开箱即用。它只可以做两件事:
- 当参数名与 匹配时注入一个参数
- 执行命名请求(当
IFactory
方法名以Get
开头时)
你能做的是写你自己定制的IInstanceProvider
。查看这个答案,它描述了如何应用您的自定义IInstanceProvider
。
IInstanceProvider
是你放置这些(定制)东西的地方。我们所做的是编写一个泛型实例提供程序,它执行一些反射来检测几个自定义属性,然后解释这些属性以允许一些事情(继承,名称匹配时注入,类型匹配时注入,约束解析,确定将实例化哪种类型,向请求添加参数,…)
自定义IInstanceProvider
,继承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();
}
}
然后像这样绑定:
kernel
.Bind<IFactory>()
.ToFactory(() => new InheritingConstructorArgumentsInstanceProvider());
单元测试,以证明它的工作
完整代码如下:
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);
}
}
}
我实现了一个自定义提供程序,它很简单:
public class InheritingConstructorArgumentsInstanceProvider : StandardInstanceProvider
{
protected override IConstructorArgument[] GetConstructorArguments(
MethodInfo methodInfo, object[] arguments)
{
var parameters = methodInfo.GetParameters();
var constructorArguments = new IConstructorArgument[parameters.Length];
for (int i = 0; i < parameters.Length; i++)
{
constructorArguments[i] = new ConstructorArgument(
parameters[i].Name, arguments[i], true);
}
return constructorArguments;
}
}
谢谢你给我指对方向!