private static void ExtractAliases(ModelConfigurationNode node, CompositionPerformer performer, List <KeyValuePair <Expression, Expression> > aliases) { if (node.GetMutators().Any()) { var conditionalSetters = performer.GetConditionalSetters(node.Path); if (conditionalSetters != null && conditionalSetters.Count == 1) { var setter = conditionalSetters.Single(); if (setter.Value == null) { var chains = setter.Key.CutToChains(true, true); if (chains.Length == 1) { var chain = chains.Single(); aliases.Add(new KeyValuePair <Expression, Expression>(node.Path, chain)); if (IsEachOrCurrent(node.Path)) { aliases.Add(new KeyValuePair <Expression, Expression>(Expression.Call(MutatorsHelperFunctions.CurrentIndexMethod.MakeGenericMethod(node.Path.Type), node.Path), Expression.Call(MutatorsHelperFunctions.CurrentIndexMethod.MakeGenericMethod(chain.Type), chain))); } } } } } else if (IsEachOrCurrent(node.Path)) { var conditionalSetters = performer.GetConditionalSetters(((MethodCallExpression)node.Path).Arguments.Single()); if (conditionalSetters != null && conditionalSetters.Count == 1) { var setter = conditionalSetters.Single(); if (setter.Value == null) { var chains = setter.Key.CutToChains(true, true); if (chains.Length == 1) { var chain = chains.Single(); chain = Expression.Call(MutatorsHelperFunctions.CurrentMethod.MakeGenericMethod(chain.Type.GetItemType()), chain); aliases.Add(new KeyValuePair <Expression, Expression>(Expression.Call(MutatorsHelperFunctions.CurrentIndexMethod.MakeGenericMethod(node.Path.Type), node.Path), Expression.Call(MutatorsHelperFunctions.CurrentIndexMethod.MakeGenericMethod(chain.Type), chain))); } } } } foreach (var child in node.Children) { ExtractAliases(child, performer, aliases); } }
private static void MigrateNode(this ModelConfigurationNode node, Type to, ModelConfigurationNode destTree, ModelConfigurationNode convertationRoot, Expression path) { var performer = new CompositionPerformer(node.RootType, to, convertationRoot); var parameters = new List <PathPrefix> { new PathPrefix(path, path.ExtractParameters().Single()) }; var abstractPathResolver = new AbstractPathResolver(parameters, false); foreach (var mutator in node.Mutators) { var mutatedMutator = mutator.Value.Mutate(to, path, performer); if (mutatedMutator == null) { continue; } var resolvedKey = abstractPathResolver.Resolve(mutator.Key); var conditionalSetters = performer.GetConditionalSetters(resolvedKey); if (conditionalSetters != null) { Qxx(destTree, conditionalSetters, mutatedMutator, performer, resolvedKey); } else { Expression mutatedPath = Expression.Constant(null); if (resolvedKey.NodeType == ExpressionType.NewArrayInit && resolvedKey.Type == typeof(object[])) { var paths = new List <Expression>(); // Mutator is set to a number of nodes foreach (var item in ((NewArrayExpression)resolvedKey).Expressions) { var mutatedItem = performer.Perform(item); if (mutatedItem.NodeType != ExpressionType.Constant || ((ConstantExpression)mutatedItem).Value != null) { paths.Add(mutatedItem); } else { // Mutator is set to a node that is either not a leaf or a leaf that is not convertible var primaryDependencies = Expression.Lambda(item, item.ExtractParameters()).ExtractPrimaryDependencies().Select(lambda => lambda.Body).ToArray(); if (primaryDependencies.Length > 1) { throw new NotSupportedException("More than one primary dependency is not supported while migrating a mutator from a non-leaf node"); } var subRoot = convertationRoot.Traverse(primaryDependencies[0], false); if (subRoot != null) { var keyLeaf = subRoot.FindKeyLeaf(); if (keyLeaf != null) { var keyLeafPath = abstractPathResolver.Resolve(keyLeaf.Path); conditionalSetters = performer.GetConditionalSetters(keyLeafPath); if (conditionalSetters != null) { paths.Add(performer.Perform(keyLeafPath)); continue; } } // The key leaf is missing or is not convertible - list all convertible subnodes var subNodes = new List <ModelConfigurationNode>(); subRoot.FindSubNodes(subNodes); paths.AddRange(subNodes.Select(subNode => performer.Perform(abstractPathResolver.Resolve(subNode.Path)))); } } } if (paths.Count > 0) { mutatedPath = Expression.NewArrayInit(typeof(object), paths.Select(exp => Expression.Convert(exp, typeof(object)))); } } else { mutatedPath = performer.Perform(resolvedKey); if (mutatedPath.NodeType == ExpressionType.Constant && ((ConstantExpression)mutatedPath).Value == null) { // Mutator is set to a node that is either not a leaf or a leaf that is not convertible var primaryDependencies = Expression.Lambda(resolvedKey, resolvedKey.ExtractParameters()).ExtractPrimaryDependencies().Select(lambda => lambda.Body).ToArray(); if (primaryDependencies.Length > 1) { throw new NotSupportedException("More than one primary dependency is not supported while migrating a mutator from a non-leaf node"); } if (primaryDependencies.Length > 0) { var subRoot = convertationRoot.Traverse(primaryDependencies[0], false); if (subRoot != null) { var keyLeaf = subRoot.FindKeyLeaf(); if (keyLeaf != null) { conditionalSetters = performer.GetConditionalSetters(abstractPathResolver.Resolve(keyLeaf.Path)); } if (conditionalSetters != null) { Qxx(destTree, conditionalSetters, mutatedMutator, performer, resolvedKey); continue; } // The key leaf is missing or is not convertible - list all convertible subnodes var subNodes = new List <ModelConfigurationNode>(); subRoot.FindSubNodes(subNodes); mutatedPath = Expression.NewArrayInit(typeof(object), subNodes.Select(subNode => Expression.Convert(performer.Perform(abstractPathResolver.Resolve(subNode.Path)), typeof(object)))); } } } } var commonPath = Expression.Lambda(mutatedPath, mutatedPath.ExtractParameters()).ExtractPrimaryDependencies().Select(lambda => lambda.Body).FindLCP(); var destNode = commonPath == null ? destTree : destTree.Traverse(commonPath, true); destNode.mutators.Add(new KeyValuePair <Expression, MutatorConfiguration>(mutatedPath, mutatedMutator)); } } }