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)); }
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; }
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); }
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); }
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); }