仅将自定义 ISpecimenBuilder 注册到特定类型
Register custom ISpecimenBuilder only to a particular type
我有一个用于 AutoFixture 的自定义样本生成器,它根据所请求的 属性 类型省略了对属性中匿名值的请求。
public class PropertyTypeExclusion<T> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
if (propertyInfo?.PropertyType == typeof(T))
{
return new OmitSpecimen();
}
return new NoSpecimen();
}
}
我可以毫无问题地将自定义添加到夹具,并且按预期工作。
_fixture.Customizations.Add(new PropertyTypeExclusion<IdentityRef>());
现在我希望将此排除项注册到特定类型的请求中。像这样:
_fixture.Customize<Release>(c => new PropertyTypeExclusion<IdentityRef>());
虽然使用 .Customize<Release>
是有效的,但它与调用 .Customizations.Add
的结果相同。
有没有办法将此 ISpecimenBuilder
注册到特定的请求类型?
如果我没理解错的话,你希望能够像这样做:
fixture.Create<Release>(); // the `IdentityRef` prop is omitted
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is NOT omitted
好的,让我们看一下这个声明:
While the use of .Customize is valid, it has the same outcome as the call to .Customizations.Add
...意味着即使您仅为 Release
类型注册自定义,other 类型也会受到影响:
fixture.Customize<Release>(c => new PropertyTypeExclusion<IdentityRef>());
fixture.Create<Release>(); // the `IdentityRef` prop is omitted which is OK
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is also omitted but it MUST NOT
对我来说这听起来像是 AF 中的一个错误,我会解决它 here...
作为您问题的快速解决方法,您可以扩展自定义以接受 class 和 属性 类型以执行更精确的过滤:
public class PropertyTypeExclusion<TType, TProp> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
if (propertyInfo?.PropertyType == typeof(TProp) &&
propertyInfo.DeclaringType == typeof(TType))
{
return new OmitSpecimen();
}
return new NoSpecimen();
}
}
现在:
fixture.Customizations.Add(new PropertyTypeExclusion<Release, IdentityRef>());
fixture.Create<Release>(); // the `IdentityRef` prop is omitted
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is NOT omitted
要完全重用现有的 AutoFixture 构建块,您只需创建一个规范即可:
public class PropertyOfTypeSpecification<TContainer, TProperty> : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
return request is PropertyInfo propertyInfo
&& propertyInfo.PropertyType == typeof(TProperty)
&& propertyInfo.ReflectedType == typeof(TContainer);
}
}
稍后您可以按如下方式自定义 Fixture:
var fixture = new Fixture();
fixture.Customizations.Add(
new Omitter(
new PropertyOfTypeSpecification<Build, IdentityRef>()));
我有一个用于 AutoFixture 的自定义样本生成器,它根据所请求的 属性 类型省略了对属性中匿名值的请求。
public class PropertyTypeExclusion<T> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
if (propertyInfo?.PropertyType == typeof(T))
{
return new OmitSpecimen();
}
return new NoSpecimen();
}
}
我可以毫无问题地将自定义添加到夹具,并且按预期工作。
_fixture.Customizations.Add(new PropertyTypeExclusion<IdentityRef>());
现在我希望将此排除项注册到特定类型的请求中。像这样:
_fixture.Customize<Release>(c => new PropertyTypeExclusion<IdentityRef>());
虽然使用 .Customize<Release>
是有效的,但它与调用 .Customizations.Add
的结果相同。
有没有办法将此 ISpecimenBuilder
注册到特定的请求类型?
如果我没理解错的话,你希望能够像这样做:
fixture.Create<Release>(); // the `IdentityRef` prop is omitted
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is NOT omitted
好的,让我们看一下这个声明:
While the use of .Customize is valid, it has the same outcome as the call to .Customizations.Add
...意味着即使您仅为 Release
类型注册自定义,other 类型也会受到影响:
fixture.Customize<Release>(c => new PropertyTypeExclusion<IdentityRef>());
fixture.Create<Release>(); // the `IdentityRef` prop is omitted which is OK
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is also omitted but it MUST NOT
对我来说这听起来像是 AF 中的一个错误,我会解决它 here...
作为您问题的快速解决方法,您可以扩展自定义以接受 class 和 属性 类型以执行更精确的过滤:
public class PropertyTypeExclusion<TType, TProp> : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
var propertyInfo = request as PropertyInfo;
if (propertyInfo?.PropertyType == typeof(TProp) &&
propertyInfo.DeclaringType == typeof(TType))
{
return new OmitSpecimen();
}
return new NoSpecimen();
}
}
现在:
fixture.Customizations.Add(new PropertyTypeExclusion<Release, IdentityRef>());
fixture.Create<Release>(); // the `IdentityRef` prop is omitted
fixture.Create<SomeOtherType>(); // the `IdentityRef` prop is NOT omitted
要完全重用现有的 AutoFixture 构建块,您只需创建一个规范即可:
public class PropertyOfTypeSpecification<TContainer, TProperty> : IRequestSpecification
{
public bool IsSatisfiedBy(object request)
{
return request is PropertyInfo propertyInfo
&& propertyInfo.PropertyType == typeof(TProperty)
&& propertyInfo.ReflectedType == typeof(TContainer);
}
}
稍后您可以按如下方式自定义 Fixture:
var fixture = new Fixture();
fixture.Customizations.Add(
new Omitter(
new PropertyOfTypeSpecification<Build, IdentityRef>()));