Oi,
Quando uso autofixture para gerar um Dictionary<T, U>
recebo valores preenchidos nele por padrão, mas com um ConcurrentDictionary<T, U>
não.
Isso é por design e devo usar um construtor de espécimes para alterar esse comportamento sozinho ou é um recurso ou bug ausente?
Se alguém mais se deparar com o mesmo problema, escrevi um construtor de espécimes para isso:
public class ConcurrentDictionaryGenerator : ISpecimenBuilder
{
public object Create(object request, ISpecimenContext context)
{
Type type = request as Type;
if (type == null)
{
return new NoSpecimen();
}
Type[] typeArguments = type.GetTypeInfo().GetGenericArguments();
if (typeArguments.Length != 2 || typeof(ConcurrentDictionary<,>).MakeGenericType(typeArguments) != type)
{
return new NoSpecimen();
}
Type nonConcurrentDictionaryType = typeof(Dictionary<,>).MakeGenericType(typeArguments);
IDictionary nonConcurrentDictionary = (IDictionary) context.Resolve(nonConcurrentDictionaryType);
IDictionary concurrentDictionary = (IDictionary) Activator.CreateInstance(type);
foreach (object key in nonConcurrentDictionary.Keys)
{
object value = nonConcurrentDictionary[key];
concurrentDictionary.Add(key, value);
}
return concurrentDictionary;
}
}
Olá,
Não posso dizer as razões por trás disso, mas olhando para o código-fonte, as coleções suportadas são codificadas.
Portanto, não é algo como "o tipo implementa o IDictionary", é "é tipo o Dicionário<,>". Portanto, ConcurrentDictionary não funciona.
Você não precisa criar seu próprio construtor de espécimes, você pode usar o que já está lá:
var fixture = new Fixture();
var query = new ModestConstructorQuery();
var methodInvoker = new MethodInvoker(query);
var dictionaryFiller = new DictionaryFiller();
var postProcessor = new Postprocessor(methodInvoker, dictionaryFiller);
var exactTypeSpecification = new ExactTypeSpecification(typeof(ConcurrentDictionary<,>));
var specimenBuilder = new FilteringSpecimenBuilder(postProcessor, exactTypeSpecification);
fixture.Customizations.Add(specimenBuilder);
Quanto mais eu aprendo sobre o interior desta biblioteca, mais eu a amo
Interessante saber que está apenas em Dictionary<,>
atualmente e obrigado pela maneira integrada de fazê-lo!
Acho que a única pergunta restante para alguém seria: esse seria um bom recurso para adicionar? Talvez não especificamente para ConcurrentDictionary<,>
, mas para todas as implementações IDictionary<,>
?
Só que eu não espalhe informações erradas, não é só Dicionário<,>. Eu só queria salientar que a lista de tipos pode ser encontrada diretamente em Fixture.cs. Por exemplo, também é SortedDictionary<,>, mas como você já descobriu, não é ConcurrentDictionary<,>.
Por todos os meios, eu diria que uma implementação futura deve verificar a interface.
Na realidade, o que está codificado não é o suporte, mas o fato de que as interfaces são retransmitidas para algum tipo concreto. Como IDictionary e IReadOnlyDictionary são retransmitidos para o Dicionário e assim por diante.
Comentários muito úteis
Olá,
Não posso dizer as razões por trás disso, mas olhando para o código-fonte, as coleções suportadas são codificadas.
Portanto, não é algo como "o tipo implementa o IDictionary", é "é tipo o Dicionário<,>". Portanto, ConcurrentDictionary não funciona.
Você não precisa criar seu próprio construtor de espécimes, você pode usar o que já está lá: