我一直在研究一个类似问题的公认答案,我认为具体工厂返回一个实现,该实现基于工厂方法上的字符串参数匹配具体实现上的命名绑定。
当工厂是抽象工厂并且我希望使用基于 Ninject 约定的绑定时,我正在努力让一个稍微复杂的示例正常工作。考虑以下测试:
[Fact]
public void VehicleBuilderFactory_Creates_Correct_Builder_For_Specified_Client()
{
// arrange
StandardKernel kernel = new StandardKernel();
kernel.Bind(typeof (IVehicleBuilderFactory<,>))
.ToFactory(() => new UseFirstArgumentAsNameInstanceProvider())
.InSingletonScope();
kernel.Bind(scanner => scanner
.FromThisAssembly()
.SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IVehicleBuilder<>))
.BindAllInterfaces());
var bicycleBuilderFactory =
kernel.Get<IVehicleBuilderFactory<IVehicleBuilder<BlueBicycle>, BlueBicycle>>();
string country = "Germany";
string localizedColor = "blau";
// act
var builder = bicycleBuilderFactory.Create<IVehicleBuilder<BlueBicycle>>(country);
Bicycle Bicycle = builder.Build(localizedColor);
// assert
Assert.IsType<BlueBicycleBuilder_Germany>(builder);
Assert.IsType<BlueBicycle>(Bicycle);
Assert.Equal(localizedColor, Bicycle.Color);
}
这是我尝试使用火把和刀具玩杂耍的地方,因为我曾经在互联网上看到过:
public class UseFirstArgumentAsNameInstanceProvider : StandardInstanceProvider
{
protected override string GetName(MethodInfo methodInfo, object[] arguments) {
return methodInfo.GetGenericArguments()[0].Name + "Builder_" + (string)arguments[0];
// ex: Germany -> 'BlueBicycle' + 'Builder_' + 'Germany' = 'BlueBicyleBuilder_Germany'
}
protected override ConstructorArgument[] GetConstructorArguments(MethodInfo methodInfo, object[] arguments) {
return base.GetConstructorArguments(methodInfo, arguments).Skip(1).ToArray();
}
}
当我尝试分配bicycleBuilderFactory
此错误时,我被刺伤并着火:
System.InvalidCastException was unhandled by user code
Message=Unable to cast object of type 'Castle.Proxies.ObjectProxy' to type 'Ninject.Extensions.Conventions.Tests.IVehicleBuilderFactory`2[Ninject.Extensions.Conventions.Tests.IVehicleBuilder`1[Ninject.Extensions.Conventions.Tests.BlueBicycle],Ninject.Extensions.Conventions.Tests.BlueBicycle]'.
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 Ninject.Extensions.Conventions.Tests.NinjectFactoryConventionsTests.VehicleBuilderFactory_Creates_Correct_Builder_For_Specified_Client() in C:\Programming\Ninject.Extensions.Conventions.Tests\NinjectFactoryConventionsTests.cs:line 40
InnerException:
是否可以使用方法和自定义提供程序进行绑定,使用工厂方法参数( )以及泛型类型参数( )来解析类型? ToFactory()
"Germany"
IVehicleBiulder<BlueBicycle>, BlueBicycle
这是测试的其余代码,尽可能紧凑和可读。
public interface IVehicleBuilderFactory<T, TVehicle>
where T : IVehicleBuilder<TVehicle> where TVehicle : IVehicle
{
T Create<T>(string country);
}
VehicleBuilder 实现
public interface IVehicleBuilder<T> where T : IVehicle { T Build(string localizedColor); }
abstract class BicycleBuilder<T> : IVehicleBuilder<T> where T : Bicycle
{
public abstract T Build(string localizedColor);
}
public abstract class RedBicycleBuilder : IVehicleBuilder<RedBicycle>
{
private readonly RedBicycle _Bicycle;
public RedBicycleBuilder(RedBicycle Bicycle) { _Bicycle = Bicycle; }
public RedBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public abstract class GreenBicycleBuilder : IVehicleBuilder<GreenBicycle>
{
private readonly GreenBicycle _Bicycle;
public GreenBicycleBuilder(GreenBicycle Bicycle) { _Bicycle = Bicycle; }
public GreenBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public abstract class BlueBicycleBuilder : IVehicleBuilder<BlueBicycle>
{
private readonly BlueBicycle _Bicycle;
public BlueBicycleBuilder(BlueBicycle Bicycle) { _Bicycle = Bicycle; }
public BlueBicycle Build(string localizedColor)
{
_Bicycle.Color = localizedColor;
return _Bicycle;
}
}
public class RedBicycleBuilder_USA : RedBicycleBuilder {
public RedBicycleBuilder_USA(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_Germany : RedBicycleBuilder {
public RedBicycleBuilder_Germany(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_France : RedBicycleBuilder {
public RedBicycleBuilder_France(RedBicycle Bicycle) : base(Bicycle) { }
}
public class RedBicycleBuilder_Default : RedBicycleBuilder {
public RedBicycleBuilder_Default(RedBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_USA : GreenBicycleBuilder {
public GreenBicycleBuilder_USA(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_Germany : GreenBicycleBuilder {
public GreenBicycleBuilder_Germany(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_France : GreenBicycleBuilder {
public GreenBicycleBuilder_France(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class GreenBicycleBuilder_Default : GreenBicycleBuilder {
public GreenBicycleBuilder_Default(GreenBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_USA : BlueBicycleBuilder
{
public BlueBicycleBuilder_USA(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_Germany : BlueBicycleBuilder {
public BlueBicycleBuilder_Germany(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_France : BlueBicycleBuilder
{
public BlueBicycleBuilder_France(BlueBicycle Bicycle) : base(Bicycle) { }
}
public class BlueBicycleBuilder_Default : BlueBicycleBuilder
{
public BlueBicycleBuilder_Default(BlueBicycle Bicycle) : base(Bicycle) { }
}
车辆实施:
public interface IVehicle { string Color { get; set; } }
public abstract class Vehicle : IVehicle { public string Color { get; set; } }
public abstract class Bicycle : Vehicle { }
public class RedBicycle : Bicycle { }
public class GreenBicycle : Bicycle { }
public class BlueBicycle : Bicycle { }