ninject - 是否可以将 Ninject Factory Extensions 的 ToFactory 方法与开放泛型一起使用?

标签 ninject ioc-container ninject-extensions abstract-factory open-generics

我正在建立之前回答的 question其中ICar实现使用 Ninject Conventions Extensions 进行绑定(bind)和定制IBindingGenerator ,以及ICarFactory接口(interface)使用Ninject Factory Extensions'绑定(bind)ToFactory()方法和custom instance provider .

我正在尝试重构,以便我可以绑定(bind)并使用 IVehicleFactory<T> ,其中T被限制为 ICar ,而不是之前的ICarFactory 。这样我就可以在泛型类型参数中指定我想要的车辆,而不用在工厂的CreateCar()中传入车辆类型的名称。方法。

是否可以使用 ToFactory() 绑定(bind)开放通用接口(interface)技术?

我有一种感觉,我找错了树,但是当我指定 ICar 时按其名称键入,似乎自然而然地指定 ICar将自身键入为泛型类型参数...

这是当前失败的测试:

[Fact]
public void A_Generic_Vehicle_Factory_Creates_A_Car_Whose_Type_Equals_Factory_Method_Generic_Type_Argument()
{
    using (StandardKernel kernel = new StandardKernel())
    {
        // arrange
        kernel.Bind(typeof(IVehicleFactory<>))
            .ToFactory(() => new UseFirstGenericTypeArgumentInstanceProvider());

        kernel.Bind(
            scanner => scanner
                           .FromThisAssembly()
                           .SelectAllClasses()
                           .InheritedFrom<ICar>()
                           .BindWith(new BaseTypeBindingGenerator<ICar>()));
        IVehicleFactory<Mercedes> factory 
            = kernel.Get<IVehicleFactory<Mercedes>>();

        // act
        var car = factory.CreateVehicle();

        // assert
        Assert.IsType<Mercedes>(car);
    }
}

还有InvalidCastException抛出:

System.InvalidCastException was unhandled by user code
  Message=Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type 'IVehicleFactory`1[Mercedes]'.
  Source=System.Core
  StackTrace:
       at System.Linq.Enumerable.<CastIterator>d__b1`1.MoveNext()
       at System.Linq.Enumerable.Single[TSource](IEnumerable`1 source)
       at Ninject.ResolutionExtensions.Get[T](IResolutionRoot root, IParameter[] parameters) in c:\Projects\Ninject\ninject\src\Ninject\Syntax\ResolutionExtensions.cs:line 37
       at NinjectFactoryTests.A_Generic_Vehicle_Factory_Creates_A_Car_Whose_Type_Name_Equals_Factory_Method_String_Argument() in C:\Programming\Ninject.Extensions.Conventions.Tests\NinjectFactoryTests.cs:line 37
  InnerException: 

以及工厂接口(interface):

public interface IVehicleFactory<T> where T : ICar
{
    T CreateVehicle();
}

还有自定义实例提供程序,我什至无法让调试器停止其断点,所以我真的不知道那里发生了什么:

public class UseFirstGenericTypeArgumentInstanceProvider : StandardInstanceProvider
{
    protected override string GetName(MethodInfo methodInfo, object[] arguments)
    {
        var genericTypeArguments = methodInfo.GetGenericArguments();
        var genericMethodDefinition = methodInfo.GetGenericMethodDefinition();
        var g = genericMethodDefinition.MakeGenericMethod(genericTypeArguments.First());
        return g.MemberType.GetType().Name;
    }

    protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments)
    {
        return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
    }
}

编辑 1 - 更改 IVehicleFactory 签名和自定义实例提供商

这是我更改的 IVehicleFactory使用通用签名 Create<T>()方法,并显式绑定(bind) Mercedes对自己来说。

public interface IVehicleFactory
{
    T CreateVehicle<T>() where T : ICar;
}

新的自定义实例提供程序返回第一个泛型类型参数的名称:

public class UseFirstGenericTypeArgumentInstanceProvider : StandardInstanceProvider
{
    protected override string GetName(MethodInfo methodInfo, object[] arguments)
    {
        var genericTypeArguments = methodInfo.GetGenericArguments();
        return genericTypeArguments[0].Name;
    }
}

这是新的测试,仍未通过:

[Fact]
public void A_Generic_Vehicle_Factory_Creates_A_Car_Whose_Type_Name_Equals_Factory_Method_String_Argument()
{
    using (StandardKernel kernel = new StandardKernel())
    {
        // arrange
        kernel.Bind<IVehicleFactory>()
            .ToFactory(() => new UseFirstGenericTypeArgumentInstanceProvider())
            .InSingletonScope();
        kernel.Bind<Mercedes>().ToSelf();
        IVehicleFactory factory = kernel.Get<IVehicleFactory>();

        // act
        var car = factory.CreateVehicle<Mercedes>();

        // assert
        Assert.IsType<Mercedes>(car);
    }
}

}

一个Ninject.ActivationException被抛出:

Ninject.ActivationException: Error activating Mercedes
No matching bindings are available, and the type is not self-bindable.
Activation path:
  1) Request for Mercedes

我不知道为什么找不到Mercedes类,因为我明确地 self 绑定(bind)了它。你能发现我做错了什么吗?

最佳答案

使用通用方法:

public interface IVehicleFactory
{
    CreateVehicle<T>();
}

关于ninject - 是否可以将 Ninject Factory Extensions 的 ToFactory 方法与开放泛型一起使用?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15891047/

相关文章:

c# - 关于 DI 和 IoC 容器的一个问题

c# - 用 Ninject 拦截。无法加载 IProxyRequestFactory

wcf - WCF 服务中的 NinjectServiceHost 不调用 Dispose()

asp.net-mvc-3 - Ninject 自定义 AuthorizeAttribute 注入(inject)不起作用

c# - Ninject 根据顶级项目获得不同实现的最佳实践

asp.net-mvc - 项目 Windsor - 存储库扩展 DataContext

wcf - Ninject 3、WCF服务和参数化构造函数

ninject - 带有 Ninject 混淆的 AutoMapper

nhibernate - NInject 和 NHibernate,坐在树上

dependency-injection - DI 容器 : inject the right components from a collection of same types?