从工厂继承ConstructorParameter

时间:2015-08-21 11:12:36

标签: c# ninject ninject-extensions

我正在使用Ninject Factory扩展程序。是否可以使自动创建的ConstructorArguments具有inherit = true?我希望以下工作:

kernel.Bind<IFactory>.ToFactory();

IFactory是:

public interface IFactory {
    View GetView(object param);
}

和param被提交给View:s依赖项(View不需要它)。

我知道我可以自己实施工厂,但我想知道Factory Extension是否有开箱即用的(无证件)支持?

2 个答案:

答案 0 :(得分:1)

不,开箱即用不支持。 只需要开箱即用的两件事:

您可以做的是编写自己的自定义IInstanceProvider。 请参阅this answer,其中介绍了如何应用自定义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);
        }
    }
}

答案 1 :(得分:1)

我实现了一个自定义提供程序,它非常简单:

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;
    }
}

感谢你让我朝着正确的方向前进!