public void Replace(MethodDefinition targetMethod) { var replacer = new MethodReplacer(targetMethod.Body); replacer.RemoveSection(); replacer.Replace(method); }
private static IEnumerable <Expression> GetArrays(Type rootType, Expression path, IEnumerable <MutatorConfiguration> mutators) { var arrays = new List <Dictionary <Type, List <Expression> > >(); var arraysExtractor = new ArraysExtractor(arrays); arraysExtractor.GetArrays(path); foreach (var mutator in mutators) { mutator.GetArrays(arraysExtractor); } var result = new List <Expression>(); var replacer = new MethodReplacer(MutatorsHelperFunctions.CurrentMethod, MutatorsHelperFunctions.EachMethod); for (var i = 1; i < arrays.Count; ++i) { var dict = arrays[i]; if (dict.Count > 1) { throw new InvalidOperationException("Too many root types"); } List <Expression> list; if (!dict.TryGetValue(rootType, out list)) { throw new InvalidOperationException("Invalid root type"); } var arraysOfCurrentLevel = list.GroupBy(exp => new ExpressionWrapper(replacer.Visit(exp), false)).Select(grouping => grouping.First()).ToArray(); if (arraysOfCurrentLevel.Length > 1) { throw new NotSupportedException("Iteration over more than one array is not supported"); } result.Add(arraysOfCurrentLevel[0]); } return(result); }
public void TestMethod_RetVoid_ArgInt() { //Assign var state = 4; var targetMethod = typeof(A_RetVoid_ArgInt).GetMethod(nameof(A_RetVoid_ArgInt.Execute)); var injectedMethod = typeof(A_RetVoid_ArgInt).GetMethod(nameof(A_RetVoid_ArgInt.ExecuteWithStateChange)); var a = new A_RetVoid_ArgInt(); a.Execute(state); var oldState = a.State; //Act MethodReplacer.Replace(targetMethod, injectedMethod); a.Execute(state); //Assert var newState = a.State; Assert.AreEqual(oldState, 0); Assert.AreEqual(newState, state); }
public static Expression RemoveLinqFirstAndSingle(this Expression expression) { expression = new MethodReplacer(firstWithoutParametersMethod, firstOrDefaultWithoutParametersMethod).Visit(expression); expression = new MethodReplacer(firstWithParametersMethod, firstOrDefaultWithParametersMethod).Visit(expression); expression = new MethodReplacer(singleWithoutParametersMethod, singleOrDefaultWithoutParametersMethod).Visit(expression); expression = new MethodReplacer(singleWithParametersMethod, singleOrDefaultWithParametersMethod).Visit(expression); return(expression); }
public void DynamicMethodCreatorTestCreate() { var targetMethod = typeof(A).GetMethod(nameof(A.Execute)); var injectedMethod = DynamicMethodCreator.DynamicMethodCreator.CreateMethodSameAsOrigial(targetMethod); MethodReplacer.Replace(targetMethod, injectedMethod); new A().Execute(); }
public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget> Set <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TTarget> configurator, Expression <Func <TSourceChild, TTarget> > value) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild); LambdaExpression valueFromRoot = pathToSourceChild.Merge(value); configurator.SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), valueFromRoot, null)); return(configurator); }
public static MutatorsConfigurator <TRoot, TChild, TValue> Required <TRoot, TChild, TValue>( this MutatorsConfigurator <TRoot, TChild, TValue> configurator, Expression <Func <TChild, TValue, MultiLanguageTextBase> > message, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); configurator.SetMutator(RequiredIfConfiguration.Create(MutatorsCreator.Sharp, priority, null, pathToValue, message.Merge(pathToChild, pathToValue), type)); return(configurator); }
public static MutatorsConfigurator <TRoot, TChild, string> IsLike <TRoot, TChild>( this MutatorsConfigurator <TRoot, TChild, string> configurator, string pattern, Expression <Func <TChild, MultiLanguageTextBase> > message, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, string> >)methodReplacer.Visit(configurator.PathToValue); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); configurator.SetMutator(RegexValidatorConfiguration.Create(MutatorsCreator.Sharp, priority, pathToValue, null, pathToChild.Merge(message), pattern, type)); return(configurator); }
protected StaticValidatorConfiguration(Type type, MutatorsCreator creator, string name, int priority, LambdaExpression condition, LambdaExpression pathToNode, LambdaExpression pathToValue, LambdaExpression validator) : base(type, creator, priority) { Name = name; Condition = condition; var replacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); PathToNode = (LambdaExpression)replacer.Visit(pathToNode); PathToValue = (LambdaExpression)replacer.Visit(pathToValue); validator = Prepare(validator); this.validator = validator; validatorFromRoot = pathToNode.Merge(validator); }
public static MutatorsConfigurator <TRoot, TChild, TValue> MustBeEqualTo <TRoot, TChild, TValue>( this MutatorsConfigurator <TRoot, TChild, TValue> configurator, Expression <Func <TChild, TValue> > expectedValue, Expression <Func <TChild, MultiLanguageTextBase> > message, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); var condition = Expression.Convert(Expression.NotEqual(pathToValue.ReplaceParameter(pathToChild.Parameters[0]).Body, pathToChild.Merge(expectedValue).Body), typeof(bool?)); configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToChild.Parameters), pathToChild.Merge(message), type)); return(configurator); }
public static MutatorsConfigurator <TRoot, TChild, TValue> IfFilledMustBelongTo <TRoot, TChild, TValue>( this MutatorsConfigurator <TRoot, TChild, TValue> configurator, IEnumerable <TValue> values, Expression <Func <TChild, TValue, MultiLanguageTextBase> > message, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); var contains = Expression.Call(containsMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body); var condition = Expression.Convert(Expression.AndAlso(Expression.NotEqual(pathToValue.Body, Expression.Constant(null, typeof(TValue))), Expression.Not(contains)), typeof(bool?)); configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), message.Merge(pathToChild, pathToValue), type)); return(configurator); }
public static MutatorsConfigurator <TRoot, TChild, string> LengthExactly <TRoot, TChild>(this MutatorsConfigurator <TRoot, TChild, string> configurator, int length, MultiLanguageTextBase title, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, string> >)methodReplacer.Visit(configurator.PathToValue); var condition = Expression.Convert(Expression.NotEqual(Expression.MakeMemberAccess(pathToValue.Body, stringLengthProperty), Expression.Constant(length)), typeof(bool?)); var message = Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(Expression.MemberInit( Expression.New(typeof(LengthNotExactlyEqualsText)), Expression.Bind(lengthNotExactlyEqualsTextExacltyProperty, Expression.Constant(length, typeof(int?))), Expression.Bind(lengthNotExactlyEqualsTextTitleProperty, Expression.Constant(title, typeof(MultiLanguageTextBase))), Expression.Bind(lengthNotExactlyEqualsTextValueProperty, pathToValue.Body)), pathToValue.Parameters); configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), message, type)); return(configurator); }
public async Task ReplaceStaticMethodFromAnotherClass() { //Assign var state = 1; var targetMethod = typeof(A).GetMethod(nameof(A.ExecuteStatic)); var injectedMethod = typeof(B).GetMethod(nameof(B.ExecuteStatic)); var oldState = await A.ExecuteStatic(state); //Act MethodReplacer.Replace(targetMethod, injectedMethod); var newState = await A.ExecuteStatic(state); //Assert Assert.AreEqual(oldState, 100); Assert.AreEqual(newState, 200); }
public async Task ReplaceNonStaticWithStaticUnexpectedBehavior() { //Assign var state = 1; var targetMethod = typeof(A_UB).GetMethod(nameof(A_UB.ExecuteStatic)); var injectedMethod = typeof(B_UB).GetMethod(nameof(B_UB.Execute)); var oldState = await A_UB.ExecuteStatic(state); //Act MethodReplacer.Replace(targetMethod, injectedMethod); var newState = await A_UB.ExecuteStatic(state); //Assert Assert.AreEqual(oldState, 100); Assert.AreNotEqual(newState, oldState); Assert.AreNotEqual(newState, 20); }
public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> Set <TSourceRoot, TSourceChild, TSourceNode, TSourceValue, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TSourceChild, TSourceNode> > node, Expression <Func <TSourceNode, TSourceValue> > value, Expression <Func <TSourceValue, TDestValue> > converter, Expression <Func <TSourceNode, ValidationResult> > validator, int priority = 0) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild); var nodeFromRoot = pathToSourceChild.Merge(node); var valueFromRoot = nodeFromRoot.Merge(value); var convertedValue = converter == null ? (LambdaExpression)valueFromRoot : valueFromRoot.Merge(converter); var validatorConfiguration = validator == null ? null : StaticValidatorConfiguration.Create(MutatorsCreator.Sharp, "SetWithValidator", priority, null, nodeFromRoot, valueFromRoot, validator); configurator.SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), convertedValue, validatorConfiguration)); return(configurator); }
public static MutatorsConfigurator <TRoot, TChild, TValue> MustBeEqualTo <TRoot, TChild, TValue>( this MutatorsConfigurator <TRoot, TChild, TValue> configurator, Expression <Func <TChild, TValue> > expectedValue, IEqualityComparer <TValue> comparer = null, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); var pathToValue = ((Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue)).ReplaceParameter(pathToChild.Parameters[0]).Body; var equal = comparer == null ? (Expression)Expression.Equal(pathToValue, pathToChild.Merge(expectedValue).Body) : Expression.Call(Expression.Constant(comparer, typeof(IEqualityComparer <TValue>)), "Equals", Type.EmptyTypes, pathToValue, pathToChild.Merge(expectedValue).Body); var condition = Expression.Convert(Expression.Not(equal), typeof(bool?)); var message = Expression.MemberInit(Expression.New(typeof(ValueMustBeEqualToText)), Expression.Bind(valueMustBeEqualToTextExpectedValueProperty, Expression.Convert(expectedValue.Body, typeof(object))), Expression.Bind(valueMustBeEqualToTextActualValueProperty, Expression.Convert(pathToValue, typeof(object)))); configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToChild.Parameters), pathToChild.Merge(Expression.Lambda <Func <TChild, MultiLanguageTextBase> >(message, expectedValue.Parameters)), type)); return(configurator); }
public async Task TestMethod_RetInt_ArgInt_Async() { //Assign var state = 4; var targetMethod = typeof(A_RetInt_ArgInt_Async).GetMethod(nameof(A_RetInt_ArgInt_Async.Execute)); var injectedMethod = typeof(A_RetInt_ArgInt_Async).GetMethod(nameof(A_RetInt_ArgInt_Async.ExecuteWithStateChange)); var a = new A_RetInt_ArgInt_Async(); var oldState = await a.Execute(state); //Act MethodReplacer.Replace(targetMethod, injectedMethod); var newState = await a.Execute(state); //Assert Assert.AreEqual(oldState, 0); Assert.AreEqual(newState, state); }
public static MutatorsConfigurator <TRoot, TChild, TValue> MustBelongTo <TRoot, TChild, TValue>( this MutatorsConfigurator <TRoot, TChild, TValue> configurator, IEnumerable <TValue> values, IEqualityComparer <TValue> comparer = null, int priority = 0, ValidationResultType type = ValidationResultType.Error) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToValue = (Expression <Func <TRoot, TValue> >)methodReplacer.Visit(configurator.PathToValue); var pathToChild = (Expression <Func <TRoot, TChild> >)methodReplacer.Visit(configurator.PathToChild); Expression contains = comparer == null ? Expression.Call(containsMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body) : Expression.Call(containsWithComparerMethod.MakeGenericMethod(typeof(TValue)), Expression.Constant(values), pathToValue.Body, Expression.Constant(comparer)); var condition = Expression.Convert(Expression.Not(contains), typeof(bool?)); var message = Expression.MemberInit(Expression.New(typeof(ValueMustBelongToText)), Expression.Bind(typeof(ValueMustBelongToText).GetMember("Value").Single(), pathToValue.Body), Expression.Bind(typeof(ValueMustBelongToText).GetMember("Values").Single(), Expression.Constant(values.Cast <object>().ToArray()))); configurator.SetMutator(InvalidIfConfiguration.Create(MutatorsCreator.Sharp, priority, Expression.Lambda <Func <TRoot, bool?> >(condition, pathToValue.Parameters), Expression.Lambda <Func <TRoot, MultiLanguageTextBase> >(message, pathToChild.Parameters), type)); return(configurator); }
public static void BatchSet <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TDestValue, TSourceChild, Batch> > batch) { var methodReplacer = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod); var pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)methodReplacer.Visit(configurator.PathToSourceChild); var pathToChild = (Expression <Func <TDestRoot, TDestChild> >)methodReplacer.Visit(configurator.PathToChild); var merger = new ExpressionMerger(pathToSourceChild); var initializers = ((ListInitExpression)batch.Body).Initializers; Expression primaryKeyIsEmpty = null; foreach (var initializer in initializers) { Expression dest = initializer.Arguments[0]; var clearedDest = ClearNotNull(dest); if (clearedDest != null) { var current = Expression.Equal(clearedDest, Expression.Constant(null, clearedDest.Type)); primaryKeyIsEmpty = primaryKeyIsEmpty == null ? current : Expression.AndAlso(primaryKeyIsEmpty, current); } dest = clearedDest ?? dest; if (dest.Type != typeof(object)) { dest = Expression.Convert(dest, typeof(object)); } Expression source = methodReplacer.Visit(initializer.Arguments[1]); // if(source.Type != typeof(object)) // source = Expression.Convert(source, typeof(object)); LambdaExpression value = merger.Merge(Expression.Lambda(source, batch.Parameters[1])); if (dest.NodeType == ExpressionType.Convert) { dest = ((UnaryExpression)dest).Operand; } dest = pathToChild.Merge(Expression.Lambda(dest, batch.Parameters[0])).Body; configurator.ToRoot().SetMutator(dest, EqualsToConfiguration.Create(typeof(TDestRoot), value, null)); //configurator.Target(Expression.Lambda<Func<TDestValue, object>>(dest, batch.Parameters[0])).SetMutator(EqualsToConfiguration.Create(typeof(TDestRoot), value, null)); } if (primaryKeyIsEmpty == null) { return; } var condition = (Expression <Func <TDestRoot, bool?> >)pathToChild.Merge(Expression.Lambda(Expression.Convert(methodReplacer.Visit(primaryKeyIsEmpty), typeof(bool?)), batch.Parameters[0])); foreach (var initializer in initializers) { Expression dest = initializer.Arguments[0]; if (ClearNotNull(dest) != null) { continue; } if (dest.Type != typeof(object)) { dest = Expression.Convert(dest, typeof(object)); } if (dest.NodeType == ExpressionType.Convert) { dest = ((UnaryExpression)dest).Operand; } dest = pathToChild.Merge(Expression.Lambda(dest, batch.Parameters[0])).Body; configurator.ToRoot().SetMutator(dest, NullifyIfConfiguration.Create(condition)); //configurator.Target(Expression.Lambda<Func<TDestValue, object>>(dest, batch.Parameters[0])).SetMutator(NullifyIfConfiguration.Create(condition)); } }
/// <summary> /// Разворачиваем всякие ичи-хуичи в нормальные циклы посредством хитровыебнутой функции MutatorsHelperFunctions.ForEach /// </summary> private static void BuildTreeMutatorForArray(this ModelConfigurationNode node, ModelConfigurationNode child, Stack <ModelConfigurationEdge> edges, ModelConfigurationNode root, List <KeyValuePair <Expression, Expression> > aliases, List <Expression> localResult, HashSet <ModelConfigurationNode> visitedNodes, HashSet <ModelConfigurationNode> processedNodes, Expression path, List <Expression> globalResult, List <ParameterExpression> invariantParameters) { // We want to transform this: // Target(target => target.A.B.Each().S).Set(source => source.T.R.Current().U.S) // To the following code: // var array = source.T.R.ToArray(); // if(target.A.B == null || target.A.B.Length != source.T.R.Length) // { // if(target.A.B == null) // { // target.A.B = new object[source.T.R.Length]; // } // else // { // var tmp = target.A.B; // Array.Resize(ref tmp, source.T.R.Length); // target.A.B = tmp; // } // } // MutatorsHelperFunctions.ForEach(target.A.B, (b, i) => // { // b.S = array[i].U.S; // return b; // }); // Create parameters for lambda to use in ForEach method and create aliases for Each() and CurrentIndex() var childParameter = Expression.Parameter(child.NodeType, child.NodeType.Name); var indexParameter = Expression.Parameter(typeof(int)); var item = node.Path.MakeEachCall(child.NodeType); var index = item.MakeCurrentIndexCall(child.NodeType); aliases.Add(new KeyValuePair <Expression, Expression>(childParameter, item)); aliases.Add(new KeyValuePair <Expression, Expression>(indexParameter, index)); // Find a source array to take values from // todo ich: почему только первый? var arrays = node.GetArrays(); var canonizedFullPath = new MethodReplacer(MutatorsHelperFunctions.EachMethod, MutatorsHelperFunctions.CurrentMethod).Visit(node.Path); var array = arrays.FirstOrDefault(pair => !new ExpressionWrapper(pair.Value, false).Equals(new ExpressionWrapper(canonizedFullPath, false))).Value; ParameterExpression arrayParameter = null; var itemType = array == null ? null : array.Type.GetItemType(); if (array != null) { // If any array found - create a variable for it and aliases for Each() and CurrentIndex() arrayParameter = Expression.Variable(itemType.MakeArrayType()); invariantParameters.Add(array.ExtractParameters().Single()); invariantParameters.Add(arrayParameter); invariantParameters.Add(indexParameter); var arrayEach = array.MakeEachCall(itemType); var arrayCurrentIndex = arrayEach.MakeCurrentIndexCall(itemType); aliases.Add(new KeyValuePair <Expression, Expression>(Expression.ArrayIndex(arrayParameter, indexParameter), arrayEach)); aliases.Add(new KeyValuePair <Expression, Expression>(indexParameter, arrayCurrentIndex)); array = array.ResolveAliases(aliases).EliminateLinq(); } // Build mutators in subtree into a separate list, to put them inside ForEach lambda var childResult = new List <Expression>(); child.BuildTreeMutator(edges, root, aliases, childResult, visitedNodes, processedNodes, globalResult, invariantParameters); // Remove all created aliases aliases.RemoveAt(aliases.Count - 1); aliases.RemoveAt(aliases.Count - 1); if (array != null) { invariantParameters.RemoveAt(invariantParameters.Count - 1); aliases.RemoveAt(aliases.Count - 1); aliases.RemoveAt(aliases.Count - 1); } if (childResult.Count > 0) { // ForEach method requires mutators block to return the target item childResult.Add(childParameter); // Optimization of block size to avoid big functions var action = Expression.Block(childResult.SplitToBatches()); // Make a call to MutatorsHelperFunctions.ForEach var forEach = action.ExtractLoopInvariantFatExpressions(invariantParameters, exp => Expression.Call(null, forEachMethod.MakeGenericMethod(child.NodeType), new[] { path, Expression.Lambda(exp, childParameter, indexParameter) })); Expression result; if (array == null) { result = forEach; } else { // If we had found an array // Assign it to the array variable with a ToArray() call. Expression assign = Expression.Assign(arrayParameter, Expression.Call(toArrayMethod.MakeGenericMethod(itemType), new[] { array })); // Add a check if target array is null or needs to be resized var resizeIfNeeded = CreateOrResizeArrayIfNeeded(child, path, arrayParameter); result = Expression.Block(new[] { arrayParameter }, assign, resizeIfNeeded, forEach); } localResult.Add(result); } if (array != null) { invariantParameters.RemoveAt(invariantParameters.Count - 1); invariantParameters.RemoveAt(invariantParameters.Count - 1); } }