public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> NullifyIf <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TDestChild, bool?> > condition) { configurator.SetMutator(NullifyIfConfiguration.Create(condition)); return(configurator); }
public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> Set <TSourceRoot, TSourceChild, TSourceValue, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TSourceChild, TSourceValue> > value, Expression <Func <TSourceValue, TDestValue> > converter) { return(configurator.Set(value, converter, null, 0)); }
private void ConfigureCustomFields(ConverterConfigurator <TSource, TDest> configurator) { var sourceParameter = Expression.Parameter(typeof(TSource)); var destParameter = Expression.Parameter(typeof(TDest)); var tree = configurator.Root; var subNodes = new List <ModelConfigurationNode>(); tree.FindSubNodes(subNodes); var dependencies = from node in subNodes from mutator in node.GetMutators() where mutator is EqualsToConfiguration from dependency in ((EqualsToConfiguration)mutator).Value.ExtractPrimaryDependencies() select new ExpressionWrapper(dependency.Body, false); var hashset = new HashSet <ExpressionWrapper>(dependencies); Func <Expression, bool> sourceCustomFieldFits = path => !hashset.Contains(new ExpressionWrapper(path, false)); Func <Expression, bool> destCustomFieldFits = path => { var node = tree.Traverse(path, false); if (node == null) { return(true); } return(node.GetMutators().Length == 0); }; ConfigureCustomFields(configurator, Expression.Lambda(sourceParameter, sourceParameter), Expression.Lambda(destParameter, destParameter), sourceCustomFieldFits, destCustomFieldFits); ConfigureCustomFieldsForArrays(configurator, typeof(TDest), Expression.Lambda(destParameter, destParameter), sourceCustomFieldFits, destCustomFieldFits); }
public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> Set <TSourceRoot, TSourceChild, TSourceValue, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TSourceChild, TSourceValue> > value, Expression <Func <TSourceValue, TDestValue> > converter, Expression <Func <TSourceValue, ValidationResult> > validator, int priority = 0) { return(configurator.Set(value, x => x, converter, validator, priority)); }
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 pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)configurator.PathToSourceChild.ReplaceEachWithCurrent(); LambdaExpression valueFromRoot = pathToSourceChild.Merge(value); configurator.SetMutator(EqualsToConfiguration.Create(configurator.Root.ConfiguratorType, typeof(TDestRoot), valueFromRoot, null)); return(configurator); }
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 ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> Set <TSourceRoot, TSourceChild, TSourceValue, TDestRoot, TDestChild, TDestValue>( this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TDestValue> configurator, Expression <Func <TSourceChild, TSourceValue> > value, Expression <Func <TSourceValue, TDestValue> > converter, Expression <Func <TSourceValue, bool?> > validator, Expression <Func <TSourceValue, MultiLanguageTextBase> > message = null, int priority = 0, ValidationResultType type = ValidationResultType.Error) { Expression test = Expression.Equal(validator.Body, Expression.Constant(true, typeof(bool?))); Expression ifTrue = Expression.New(validationResultConstructor, Expression.Constant(type), Expression.Lambda(validator.Parameters[0], validator.Parameters[0]).Merge(message).Body); Expression ifFalse = Expression.Constant(ValidationResult.Ok); return(configurator.Set(value, converter, Expression.Lambda <Func <TSourceValue, ValidationResult> >(Expression.Condition(test, ifTrue, ifFalse), validator.Parameters), priority)); }
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 pathToSourceChild = (Expression <Func <TSourceRoot, TSourceChild> >)configurator.PathToSourceChild.ReplaceEachWithCurrent(); 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(configurator.Root.ConfiguratorType, typeof(TDestRoot), convertedValue, validatorConfiguration)); return(configurator); }
private void ConfigureCustomFieldsForArrays(ConverterConfigurator <TSource, TDest> configurator, Type type, LambdaExpression pathToDestChild, Func <Expression, bool> sourceCustomFieldFits, Func <Expression, bool> destCustomFieldFits) { if (type == null || IsALeaf(type)) { return; } var tree = configurator.Root; var properties = type.GetOrderedProperties(); var parameter = Expression.Parameter(type); foreach (var property in properties) { if (property.GetGetMethod().GetParameters().Length != 0) { continue; } var pathToNextDestChild = pathToDestChild.Merge(Expression.Lambda(Expression.Property(parameter, property), parameter)); if (!property.PropertyType.IsArray) { ConfigureCustomFieldsForArrays(configurator, property.PropertyType, pathToNextDestChild, sourceCustomFieldFits, destCustomFieldFits); } else { var pathToDestArray = pathToNextDestChild.Body; var node = tree.Traverse(pathToDestArray, false); if (node == null) { continue; } var arrays = node.GetArrays(); if (!arrays.TryGetValue(typeof(TSource), out var pathToSourceArray)) { continue; } var pathToDestArrayItem = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(pathToDestArray.Type.GetItemType()), pathToDestArray); var pathToSourceArrayItem = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(pathToSourceArray.Type.GetItemType()), pathToSourceArray); ConfigureCustomFields(configurator, Expression.Lambda(pathToSourceArrayItem, pathToSourceArray.ExtractParameters()), Expression.Lambda(pathToDestArrayItem, pathToDestArray.ExtractParameters()), sourceCustomFieldFits, destCustomFieldFits); } } }
public static ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TValue> Set <TSourceRoot, TSourceChild, TValue, TDestRoot, TDestChild>(this ConverterConfigurator <TSourceRoot, TSourceChild, TDestRoot, TDestChild, TValue> configurator, TValue value) { return(configurator.Set(child => value)); }
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)); } }
protected abstract void Configure(MutatorsContext context, ConverterConfigurator <TSource, TDest> configurator);
protected void ConfigureInternal(MutatorsContext context, ConverterConfigurator <TSource, TDest> configurator) { Configure(context, configurator); ConfigureCustomFields(configurator); }
private void ConfigureCustomFields(ConverterConfigurator <TSource, TDest> configurator, LambdaExpression pathToSourceChild, LambdaExpression pathToDestChild, Func <Expression, bool> sourceCustomFieldFits, Func <Expression, bool> destCustomFieldFits) { var sourceChildType = pathToSourceChild.Body.Type; var destChildType = pathToDestChild.Body.Type; LambdaExpression pathToSourceCustomFieldsContainer; var sourceCustomFieldsContainer = FindCustomFieldsContainer(sourceChildType, out pathToSourceCustomFieldsContainer); var sourceCustomFields = FindCustomFields(sourceChildType, sourceCustomFieldFits, pathToSourceChild); LambdaExpression pathToDestCustomFieldsContainer; var destCustomFieldsContainer = FindCustomFieldsContainer(destChildType, out pathToDestCustomFieldsContainer); var destCustomFields = FindCustomFields(destChildType, destCustomFieldFits, pathToDestChild); var converterType = configurator.Root.ConfiguratorType; if (sourceCustomFields.Length > 0) { if (destCustomFields.Length > 0 || sourceCustomFieldsContainer != null) { throw new InvalidOperationException(); } if (destCustomFieldsContainer == null) { return; } var destParameter = pathToDestCustomFieldsContainer.Parameters.Single(); var indexerGetter = destCustomFieldsContainer.PropertyType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); foreach (var customField in sourceCustomFields) { var path = customField.Path; var rootProperty = customField.RootProperty; var titleType = customField.TitleType; var value = customField.Value; TypeCode typeCode; LambdaExpression convertedValue; if (stringConverter != null && stringConverter.CanConvert(value.Body.Type)) { typeCode = TypeCode.String; convertedValue = Expression.Lambda( Expression.Call(Expression.Constant(stringConverter, typeof(IStringConverter)), convertToStringMethod.MakeGenericMethod(value.Body.Type), Expression.Convert(value.Body, typeof(object))), value.Parameters); } else { typeCode = GetTypeCode(value.Body.Type); convertedValue = value; } if (rootProperty.PropertyType.IsArray && !IsALeaf(rootProperty.PropertyType)) { // An array of complex types var delimiterIndex = path.IndexOf('ё'); var pathToArray = path.Substring(0, delimiterIndex); var pathToLeaf = path.Substring(delimiterIndex + 1, path.Length - delimiterIndex - 1); var pathToTarget = pathToDestChild.Merge(Expression.Lambda(Expression.Call(pathToDestCustomFieldsContainer.Body, indexerGetter, Expression.Constant(pathToArray)), destParameter)).Body; configurator.SetMutator(Expression.Property(pathToTarget, "TypeCode"), EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(TypeCode.Object)))); configurator.SetMutator(Expression.Property(pathToTarget, "IsArray"), EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(true)))); var pathToDestArrayItem = Expression.Convert(Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(typeof(object)), Expression.Convert(Expression.Property(pathToTarget, "Value"), typeof(object[]))), typeof(Hashtable)); var itemIndexerGetter = typeof(Hashtable).GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); var pathToDestArrayItemValue = Expression.Call(pathToDestArrayItem, itemIndexerGetter, Expression.Constant(pathToLeaf)); configurator.SetMutator(pathToDestArrayItemValue, EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(convertedValue))); var pathToTypeCodes = Expression.Property(pathToTarget, "TypeCodes"); var pathToItemTypeCode = Expression.Call(pathToTypeCodes, pathToTypeCodes.Type.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(), Expression.Constant(pathToLeaf)); configurator.SetMutator(pathToItemTypeCode, EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(typeCode)))); if (value.Body is MemberExpression) { var member = ((MemberExpression)value.Body).Member; var customFieldAttribute = member.GetCustomAttributes(typeof(CustomFieldAttribute), false).SingleOrDefault() as CustomFieldAttribute; if (customFieldAttribute != null && customFieldAttribute.TitleType != null) { var pathToTitles = Expression.Property(pathToTarget, "Titles"); var pathToItemTitle = Expression.Call(pathToTitles, pathToTitles.Type.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(), Expression.Constant(pathToLeaf)); configurator.SetMutator(pathToItemTitle, EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(StaticMultiLanguageTextCache.Get(customFieldAttribute.TitleType))))); } } } else { var pathToTarget = pathToDestChild.Merge(Expression.Lambda(Expression.Call(pathToDestCustomFieldsContainer.Body, indexerGetter, Expression.Constant(path)), destParameter)).Body; configurator.SetMutator(Expression.Property(pathToTarget, "TypeCode"), EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(typeCode)))); configurator.SetMutator(Expression.Property(pathToTarget, "IsArray"), EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(convertedValue.Body.Type.IsArray)))); configurator.SetMutator(Expression.Property(pathToTarget, "Value"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(convertedValue))); if (titleType != null) { configurator.SetMutator(Expression.Property(pathToTarget, "Title"), EqualsToConfiguration.Create <TDest>(converterType, Expression.Lambda(Expression.Constant(StaticMultiLanguageTextCache.Get(titleType))))); } } } } else if (destCustomFields.Length > 0) { if (destCustomFieldsContainer != null) { throw new InvalidOperationException(); } if (sourceCustomFieldsContainer == null) { return; } var sourceParameter = pathToSourceCustomFieldsContainer.Parameters.Single(); var indexerGetter = sourceCustomFieldsContainer.PropertyType.GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(); foreach (var customField in destCustomFields) { var path = customField.Path; var rootProperty = customField.RootProperty; var pathToTarget = pathToDestChild.Merge(customField.Value).Body; if (rootProperty.PropertyType.IsArray && !IsALeaf(rootProperty.PropertyType.GetElementType())) { var delimiterIndex = path.IndexOf('ё'); var pathToArray = path.Substring(0, delimiterIndex); var pathToLeaf = path.Substring(delimiterIndex + 1, path.Length - delimiterIndex - 1); Expression value = Expression.Property(Expression.Call(pathToSourceCustomFieldsContainer.Body, indexerGetter, Expression.Constant(pathToArray)), "Value"); value = Expression.Convert(Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(typeof(object)), Expression.Convert(value, typeof(object[]))), typeof(Hashtable)); value = Expression.Call(value, typeof(Hashtable).GetProperty("Item", BindingFlags.Public | BindingFlags.Instance).GetGetMethod(), Expression.Constant(pathToLeaf)); var convertedValue = MakeConvert(value, pathToTarget.Type); configurator.SetMutator(pathToTarget, EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(convertedValue, sourceParameter)))); } else { Expression value = Expression.Property(Expression.Call(pathToSourceCustomFieldsContainer.Body, indexerGetter, Expression.Constant(path)), "Value"); var convertedValue = MakeConvert(value, pathToTarget.Type); configurator.SetMutator(pathToTarget, EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(convertedValue, sourceParameter)))); } } } else { if (sourceCustomFieldsContainer == null || destCustomFieldsContainer == null) { return; } var destParameter = pathToDestCustomFieldsContainer.Parameters.Single(); var sourceParameter = pathToSourceCustomFieldsContainer.Parameters.Single(); Expression pathToDestCustomContainer = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(destCustomFieldsContainer.PropertyType.GetItemType()), pathToDestCustomFieldsContainer.Body); Expression pathToSourceCustomContainer = Expression.Call(MutatorsHelperFunctions.EachMethod.MakeGenericMethod(sourceCustomFieldsContainer.PropertyType.GetItemType()), pathToSourceCustomFieldsContainer.Body); var pathToTarget = pathToDestChild.Merge(Expression.Lambda(Expression.Property(pathToDestCustomContainer, "Key"), destParameter)).Body; Expression value = Expression.Property(pathToSourceCustomContainer, "Key"); configurator.SetMutator(pathToTarget, EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(value, sourceParameter)))); value = Expression.Property(pathToSourceCustomContainer, "Value"); pathToTarget = pathToDestChild.Merge(Expression.Lambda(Expression.Property(pathToDestCustomContainer, "Value"), destParameter)).Body; configurator.SetMutator(Expression.Property(pathToTarget, "TypeCode"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "TypeCode"), sourceParameter)))); configurator.SetMutator(Expression.Property(pathToTarget, "TypeCodes"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "TypeCodes"), sourceParameter)))); configurator.SetMutator(Expression.Property(pathToTarget, "Titles"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "Titles"), sourceParameter)))); configurator.SetMutator(Expression.Property(pathToTarget, "IsArray"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "IsArray"), sourceParameter)))); configurator.SetMutator(Expression.Property(pathToTarget, "Value"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "Value"), sourceParameter)))); configurator.SetMutator(Expression.Property(pathToTarget, "Title"), EqualsToConfiguration.Create <TDest>(converterType, pathToSourceChild.Merge(Expression.Lambda(Expression.Property(value, "Title"), sourceParameter)))); } }