从工厂继承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不需要它)。

我知道我可以自己实现工厂,但我想知道工厂扩展是否有任何(未记录的)开箱即用的支持?

从工厂继承ConstructorParameter

不,这是不支持开箱即用。它只可以做两件事:

  • 当参数名与
  • 匹配时注入一个参数
  • 执行命名请求(当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;
    }
}

谢谢你给我指对方向!

相关文章:
  • 没有找到相关文章