protected override IEnumerable <TMember> CreateManyValues( ValueProviderContext <TMember> context, [CanBeNull] IList <object> metadatas, int itemCount) { var typeInfo = context.Advanced.FastReflection.GetTypeInfo(context.Advanced.Key.Type); var ctorValuesCollections = InitializeCtorValues(itemCount, typeInfo); var ctorMembers = typeInfo.CtorArguments.Select( c => c.ToMember(context.Advanced.ParameterConversionService)).ToList(); var sortedCtorMembers = context.Advanced.MemberSorter.Sort(ctorMembers, context.Advanced.Key).ToList(); //Note: We use a dictionary because when we have many ctor members, we gain some performance. var toUnsortedDictionary = ctorMembers.Select((value, index) => new { value, index }).ToDictionary(x => x.value, x => x.index); var sortedToUnsorted = sortedCtorMembers.Select(member => toUnsortedDictionary[member]).ToList(); List <object> resolvedMetadatas = null; for (var argumentIndex = 0; argumentIndex < sortedCtorMembers.Count; argumentIndex++) { var ctorMember = sortedCtorMembers[argumentIndex]; var unsortedArgumentIndex = sortedToUnsorted[argumentIndex]; var memberKey = context.Advanced.Key.CreateKey(ctorMember); //we only resolve once per parent (not for each member), so the data is shared between all members. if (resolvedMetadatas == null && context.Advanced.MetadataResolver.NeedsMetadata(memberKey)) { var dependendArguments = sortedCtorMembers.Take(argumentIndex).ToList(); var metadataContexts = GetMetadataContexts( context.Advanced.Key, dependendArguments, ctorValuesCollections, sortedToUnsorted, context.TestDataGenerator).ToList(); resolvedMetadatas = context.Advanced.MetadataResolver.Resolve(memberKey, metadataContexts).ToList(); } //Note: Here we have a recursion to the compound value provider. e.g. other immutable types could be a ctor argument var ctorMemberValues = context.Advanced.AdvancedTestDataGenerator.CreateMany(memberKey, resolvedMetadatas, itemCount, maxRecursionDepth: 2); for (var valueIndex = 0; valueIndex < ctorMemberValues.Count; valueIndex++) { ctorValuesCollections[valueIndex][unsortedArgumentIndex] = ctorMemberValues[valueIndex]; } } var typeFactoryWithArguments = FastActivator.GetFactory(context.Advanced.Key.Type, typeInfo.CtorArguments); return(ctorValuesCollections.Select(ctorValues => typeFactoryWithArguments(ctorValues)).Cast <TMember>()); }
public FastActivatorSpeck() { Specify(x => FastActivator.GetFactory(TypeToCreate, new IFastArgumentInfo[0])) .Case("creates something", _ => _ .Given("object type", x => TypeToCreate = typeof(object)) .It("creates an valid object function", x => x.Result.Should().BeOfType(typeof(Func <object[], object>))) .It("creates a function that returns not null", x => x.Result.Should().NotBeNull()) .It("creates a new object every time", x => x.Result(new object[0]).Should().NotBeSameAs(x.Result(new object[0])))) .Case("throws for value type", _ => _ .Given("value type", x => TypeToCreate = typeof(int)) .ItThrows(typeof(NotSupportedException), x => "Primitive types are not supported. Please configure a value provider for type System.Int32.")) .Case("throws for type with no default constructor", _ => _ .Given("ClassWithNoDefaultConstructor", x => TypeToCreate = typeof(ClassWithNoDefaultConstructor)) .ItThrows(typeof(NotSupportedException), x => "No valid ctor found on 'Farada.TestDataGeneration.UnitTests.FastReflection.ClassWithNoDefaultConstructor': Classes with non-public constructors and abstract classes are not supported.")) .Case("throws for type with private constructor", _ => _ .Given("ClassWithPrivateConstructor", x => TypeToCreate = typeof(ClassWithPrivateConstructor)) .ItThrows(typeof(NotSupportedException), x => "No valid ctor found on 'Farada.TestDataGeneration.UnitTests.FastReflection.ClassWithPrivateConstructor': Classes with non-public constructors and abstract classes are not supported.")) .Case("throws for type with internal constructor", _ => _ .Given("ClassWithInternalConstructor", x => TypeToCreate = typeof(ClassWithInternalConstructor)) .ItThrows(typeof(NotSupportedException), x => "No valid ctor found on 'Farada.TestDataGeneration.UnitTests.FastReflection.ClassWithInternalConstructor': Classes with non-public constructors and abstract classes are not supported.")); }