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>());
        }
Ejemplo n.º 2
0
 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."));
 }