Ejemplo n.º 1
0
        private static Expression NextFactory(Type type, RecursionGuard recursion)
        {
            if (recursion.TypeInRecursionStack(type))
            {
                // End the recursion.
                return(Expression.Constant(null, type));
            }

            if (TryGetTypeFactory(type, out var tf))
            {
                return(tf);
            }

            if (TryGetDictionaryFactory(type, recursion, out var df))
            {
                return(df);
            }

            if (TryGetListFactory(type, recursion, out var lf))
            {
                return(lf);
            }

            if (TryGetCollectionFactory(type, recursion, out var af))
            {
                return(af);
            }

            var nextRecursion = new RecursionGuard(recursion, type);

            var defaultContructor = type.GetConstructor(Type.EmptyTypes);

            if (defaultContructor != null)
            {
                var properties = type.GetProperties().Where(x => x.CanWrite).ToArray();
                if (properties.Any())
                {
                    // We have an empty constructor and some public properties lets just call that and set... them.
                    var propertyBindings = properties
                                           .Select(p => (MemberBinding)Expression.Bind(p, NextFactory(p.PropertyType, nextRecursion)))
                                           .ToArray();
                    return(Expression.MemberInit(Expression.New(type), propertyBindings));
                }
            }

            var(constructor, parameters) = type.GetConstructors()
                                           .Select(c => (c, parameters: c.GetParameters()))
                                           .OrderByDescending(x => x.parameters.Length)
                                           .FirstOrDefault();

            if (constructor == null)
            {
                throw new ArgumentException("No public constructors: " + type, nameof(type));
            }

            // Use constructor... it's probably there for a reason.
            var parameterExpressions = parameters.Select(p => NextFactory(p.ParameterType, nextRecursion)).ToArray();

            return(Expression.New(constructor, parameterExpressions));
        }
Ejemplo n.º 2
0
        public RecursionGuard(RecursionGuard previous, Type type)
        {
            var previousStackLength = previous._typeStack.Length;

            _typeStack = new Type[previousStackLength + 1];
            Array.Copy(previous._typeStack, _typeStack, previousStackLength);
            _typeStack[previousStackLength] = type;
        }
Ejemplo n.º 3
0
        private static bool TryGetCollectionFactory(Type type, RecursionGuard recursion, out Expression f)
        {
            var elementType = GetCollectionElementType(type);

            if (elementType == null)
            {
                f = null;
                return(false);
            }

            var nextRecursion      = new RecursionGuard(recursion, type);
            var elementTypeFactory = NextFactory(elementType, nextRecursion);
            var size = Rng.Int(MinimumCollectionSize, MaximumCollectionSize);

            f = Expression.NewArrayInit(elementType, Enumerable.Repeat(elementTypeFactory, size));

            return(true);
        }
Ejemplo n.º 4
0
        private static bool TryGetListFactory(Type type, RecursionGuard recursion, out Expression f)
        {
            var elementType = IsGenericType(type, typeof(List <>)) ? type.GenericTypeArguments.FirstOrDefault() : null;

            if (elementType == null)
            {
                f = null;
                return(false);
            }

            var nextRecursion = new RecursionGuard(recursion, type);
            var entryFactory  = NextFactory(elementType, nextRecursion);
            var addMethod     = type.GetMethod("Add");
            var size          = Rng.Int(MinimumCollectionSize, MaximumCollectionSize);
            var entries       = Enumerable.Range(0, size).Select(_ => Expression.ElementInit(addMethod, entryFactory)).ToArray();

            f = Expression.ListInit(Expression.New(type), entries);
            return(true);
        }
Ejemplo n.º 5
0
        private static bool TryGetDictionaryFactory(Type type, RecursionGuard recursion, out Expression f)
        {
            var(key, value) = GetDictionaryElementTypes(type);
            if (key == null || value == null)
            {
                f = null;
                return(false);
            }

            var nextRecursion = new RecursionGuard(recursion, type);
            var keyFactory    = NextFactory(key, nextRecursion);
            var valueFactory  = NextFactory(value, nextRecursion);

            var dictionaryType = typeof(Dictionary <,>).MakeGenericType(key, value);
            var addMethod      = dictionaryType.GetMethod("Add");

            var size    = Rng.Int(MinimumCollectionSize, MaximumCollectionSize);
            var entries = Enumerable.Range(0, size).Select(_ => Expression.ElementInit(addMethod, keyFactory, valueFactory)).ToArray();

            f = Expression.ListInit(Expression.New(dictionaryType), entries);
            return(true);
        }