我正在构建之前回答的问题,其中ICar
使用Ninject Conventions Extensions和自定义IBindingGenerator绑定实现,并且使用Ninject Factory Extensions 的方法和自定义实例提供程序ICarFactory
绑定接口。 ToFactory()
我正在尝试重构,以便我可以绑定和使用 a IVehicleFactory<T>
,其中T
被限制为ICar
,而不是之前的ICarFactory
. 这样,我可以在泛型类型参数中指定我想要的车辆,而不是在工厂的CreateCar()
方法中传入车辆类型的名称。
是否可以使用该ToFactory()
技术绑定开放的通用接口?
我有一种感觉,我在吠叫错误的树,但是当我通过它的名称指定一个类型时,将类型本身指定为泛型类型参数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:
和工厂界面:
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>()
方法,并显式绑定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);
}
}
}
ANinject.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
类,因为我明确地对它进行了自我绑定。你能看出我做错了什么吗?