\n我一直在尝试对一些简单的不可变对象进行建模,其中我有两个构造函数重载:一个重载接受每个只读属性的参数,另一个重载接受其自身的实例以进行克隆(以便在大多数属性值将与另一个实例的相同)。
\n\npublic class Parent {\n public Parent(Child child, Pet pet) {\n Child = child;\n Pet = pet;\n }\n\n public Parent(Parent template) {\n Child = template.Child;\n Pet = template.Pet;\n }\n\n public Child Child { get; private set; }\n public Pet Pet { get; private set; }\n}\nRun Code Online (Sandbox Code Playgroud)\n\n正如我所期望的,这个测试通过了:
\n\n[Theory]\n[AutoData]\npublic void Properties_Equal_Constructor_Arguments(Child expectedChild, Pet expectedPet)\n{\n // act\n var sut = new Parent(expectedChild, expectedPet);\n\n // assert\n sut.Child.Should().Be(expectedChild);\n sut.Pet.Should().Be(expectedPet);\n}\nRun Code Online (Sandbox Code Playgroud)\n\n但是这个测试抛出一个Ploeh.AutoFixture.ObjectCreationException,无法创建类型的实例System.Reflection.RuntimeParameterInfo(使用 AutoData 参数),或类型Ploeh.AutoFixture.Kernel.SeededRequest(不使用 AutoData)(?!?)
如何使用Ninject约定将InitializerForXXX(非泛型实现)绑定到IInitializer<XXX>(通用接口),以便请求解析名称以InitializerFor开头并以以下结尾的非泛型实现:IInitializer<T>typeof(T).Name
initializerFactory.CreateFor<Blue>(); //resolves InitializerOfBlue
initializerFactory.CreateFor<ShadeOfBlue>(); //resolves InitializerOfShadeOfBlue
Run Code Online (Sandbox Code Playgroud)
其中没有非抽象类直接实现IInitializer<T>,而某些实现继承自其他实现:
InitializerForShadeOfBlue 继承自 InitializerForBlueInitializerForBlue 继承自抽象 Initializer<Blue>Initializer<T>直接实现IInitializer<T>我希望我可以使用一个我可以使用的.EndsWith(typeof(T).Name)给定IInitializer<T>约定,因为在ShadeOfxxx静脉中有数百个初始化器.如果我必须映射所有这些,我最好找到一种在运行时使用反射解决的方法.
鉴于以下内容:
更新:与自定义绑定生成器的绑定(请参阅下面的答案以实现)
void Bootstrap(IBindingRoot kernel)
{
kernel.Bind<IInitializerFactory>()
.To<InitializerFactory>()
.InSingletonScope();
kernel.Bind(scanner =>
scanner.FromThisAssembly().SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IComplexContent))
.BindAllInterfaces());
kernel.Bind(scanner =>
scanner.FromThisAssembly().SelectAllClasses()
.WhichAreNotGeneric()
.InheritedFrom(typeof(IInitializer<>))
.BindWith<FirstTypeParameterNameMatchesEndOfBoundClassNameGenerator>());
}
Run Code Online (Sandbox Code Playgroud)
主要方法
void Main(IEnumerable<string> values)
{
// setup bindings
var kernel = new StandardKernel();
Bootstrap(kernel);
IInitializerFactory initializerFactory =
kernel.Get<IInitializerFactory>();
IInitializer<ShadeOfBlueComplexContent> initializer = …Run Code Online (Sandbox Code Playgroud) ninject ioc-container ninject-extensions ninject-conventions open-generics
我在xUnit单元测试中使用AutoData.我偶尔需要为我的测试提供特定数量的对象.考虑以下课程:
public class Recipient
{
public void Receive(
CallingBird bird1,
CallingBird bird2,
CallingBird bird3,
CallingBird bird4
)
{
this.Bird1 = bird1;
this.Bird2 = bird2;
this.Bird3 = bird3;
this.Bird4 = bird4;
}
public CallingBird Bird1 { get; private set; }
public CallingBird Bird2 { get; private set; }
public CallingBird Bird3 { get; private set; }
public CallingBird Bird4 { get; private set; }
}
Run Code Online (Sandbox Code Playgroud)
没有AutoData,我可能会写一个这样的测试:
[Fact]
public void All_Birds_Are_Populated()
{
var bird1 = new CallingBird();
var bird2 = …Run Code Online (Sandbox Code Playgroud) 考虑以下测试,
[Theory, MyConventions]
public void GetClientExtensionReturnsCorrectValue(BuilderStrategy sut)
{
var expected = ""; // <--??? the value injected into BuilderStrategy
var actual = sut.GetClientExtension();
Assert.Equal(expected, actual);
}
Run Code Online (Sandbox Code Playgroud)
和我正在使用的自定义属性:
public class MyConventionsAttribute : AutoDataAttribute {
public MyConventionsAttribute()
: base(new Fixture().Customize(new AutoMoqCustomization())) {}
}
Run Code Online (Sandbox Code Playgroud)
和SUT:
class BuilderStrategy {
private readonly string _clientID;
private readonly IDependency _dependency;
public void BuilderStrategy(string clientID, IDependency dependency) {
_clientID = clientID;
_dependency = dependency;
}
public string GetClientExtension() {
return _clientID.Substring(_clientID.LastIndexOf("-") + 1);
}
}
Run Code Online (Sandbox Code Playgroud)
我需要知道在构造函数参数中注入了什么值,clientID以便我可以使用它来与输出进行比较 …