我正在建立之前回答的 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/