private CompileArgument GetCompileArgument(TypeTuple tuple, MapType mapType, CompileContext context) { var setting = GetMergedSettings(tuple, mapType); return(new CompileArgument { SourceType = tuple.Source, DestinationType = tuple.Destination, ExplicitMapping = this.RuleMap.ContainsKey(tuple), MapType = mapType, Context = context, Settings = setting, }); }
private LambdaExpression CreateProjectionExpression(TypeTuple tuple) { var context = new CompileContext(this); context.Running.Add(tuple); try { return(CreateMapExpression(tuple.Source, tuple.Destination, MapType.Projection, context)); } finally { context.Running.Remove(tuple); } }
internal LambdaExpression CreateMapExpression(TypeTuple tuple, MapType mapType) { var context = new CompileContext(this); context.Running.Add(tuple); try { var arg = GetCompileArgument(tuple, mapType, context); return(CreateMapExpression(arg)); } finally { context.Running.Remove(tuple); } }
private Delegate CreateMapToTargetFunction(TypeTuple tuple) { var context = new CompileContext(this); context.Running.Add(tuple); try { var result = CreateMapExpression(tuple.Source, tuple.Destination, MapType.MapToTarget, context); return(result.Compile()); } finally { context.Running.Remove(tuple); } }
private Delegate CreateMapFunction(TypeTuple tuple) { var context = new CompileContext(this); context.Running.Add(tuple); try { var result = CreateMapExpression(tuple.Source, tuple.Destination, MapType.Map, context); var compiled = result.Compile(); if (this == GlobalSettings) { var field = typeof(TypeAdapter <,>).MakeGenericType(tuple.Source, tuple.Destination).GetField("Map"); field.SetValue(null, compiled); } return(compiled); } finally { context.Running.Remove(tuple); } }
private MethodCallExpression CreateProjectionCallExpression(TypeTuple tuple) { var context = new CompileContext(this); context.Running.Add(tuple); try { var lambda = CreateMapExpression(tuple.Source, tuple.Destination, MapType.Projection, context); var source = Expression.Parameter(typeof(IQueryable <>).MakeGenericType(tuple.Source)); var methodInfo = (from method in typeof(Queryable).GetMethods() where method.Name == "Select" let p = method.GetParameters()[1] where p.ParameterType.GetGenericArguments()[0].GetGenericTypeDefinition() == typeof(Func <,>) select method).First().MakeGenericMethod(tuple.Source, tuple.Destination); return(Expression.Call(methodInfo, source, Expression.Quote(lambda))); } finally { context.Running.Remove(tuple); } }
internal LambdaExpression CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context, MemberMapping?mapping = null) { var tuple = new TypeTuple(sourceType, destinationType); var subFunction = context.IsSubFunction(); if (!subFunction) { if (context.Running.Contains(tuple)) { if (mapType == MapType.Projection) { throw new InvalidOperationException("Projection does not support circular reference"); } return(CreateMapInvokeExpression(sourceType, destinationType, mapType)); } context.Running.Add(tuple); } try { var arg = GetCompileArgument(tuple, mapType, context); if (mapping != null) { arg.Settings.Resolvers.AddRange(mapping.NextResolvers); arg.Settings.Ignore.Apply(mapping.NextIgnore); arg.UseDestinationValue = mapping.UseDestinationValue; } return(CreateMapExpression(arg)); } finally { if (!subFunction) { context.Running.Remove(tuple); } } }
internal LambdaExpression CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context) { var tuple = new TypeTuple(sourceType, destinationType); if (context.Running.Contains(tuple)) { return(CreateInvokeExpression(sourceType, destinationType)); } context.Running.Add(tuple); try { var exp = CreateMapExpression(sourceType, destinationType, mapType == MapType.Projection ? MapType.Projection : MapType.InlineMap, context); if (exp != null) { var detector = new BlockExpressionDetector(); detector.Visit(exp); if (detector.IsBlockExpression) { exp = null; } } return(exp ?? CreateInvokeExpression(sourceType, destinationType)); } finally { context.Running.Remove(tuple); } }
private LambdaExpression CreateMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context) { var setting = GetMergedSettings(sourceType, destinationType, mapType); var fn = mapType == MapType.MapToTarget ? setting.ConverterToTargetFactory : setting.ConverterFactory; if (fn == null) { if (mapType == MapType.InlineMap) { return(null); } else { throw new InvalidOperationException( $"ConverterFactory is not found for the following mapping: TSource: {sourceType} TDestination: {destinationType}"); } } var arg = new CompileArgument { SourceType = sourceType, DestinationType = destinationType, MapType = mapType, Context = context, Settings = setting, }; return(fn(arg)); }
internal LambdaExpression CreateInlineMapExpression(Type sourceType, Type destinationType, MapType parentMapType, CompileContext context) { var tuple = new TypeTuple(sourceType, destinationType); if (context.Running.Contains(tuple)) { if (parentMapType == MapType.Projection) { throw new InvalidOperationException("Projection does not support circular reference"); } return(CreateMapInvokeExpression(sourceType, destinationType)); } context.Running.Add(tuple); try { var arg = GetCompileArgument(tuple, parentMapType, context); var exp = CreateMapExpression(arg, true); if (exp != null) { var detector = new BlockExpressionDetector(); detector.Visit(exp); if (detector.IsBlockExpression) { exp = null; } } if (exp != null) { return(exp); } if (parentMapType == MapType.MapToTarget) { return(CreateMapToTargetInvokeExpression(sourceType, destinationType)); } else { return(CreateMapInvokeExpression(sourceType, destinationType)); } } finally { context.Running.Remove(tuple); } }
internal LambdaExpression CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context) { var tuple = new TypeTuple(sourceType, destinationType); if (context.Running.Contains(tuple)) { if (mapType == MapType.Projection) { throw new InvalidOperationException( $"Projection does not support circular reference: TSource: {sourceType} TDestination: {destinationType}"); } return(CreateInvokeExpression(sourceType, destinationType)); } context.Running.Add(tuple); try { var exp = CreateMapExpression(sourceType, destinationType, mapType == MapType.Projection ? MapType.Projection : MapType.InlineMap, context); if (exp != null) { var detector = new BlockExpressionDetector(); detector.Visit(exp); if (detector.IsBlockExpression) { exp = null; } } return(exp ?? CreateInvokeExpression(sourceType, destinationType)); } finally { context.Running.Remove(tuple); } }
CompileArgument GetCompileArgument(Type sourceType, Type destinationType, MapType mapType, CompileContext context) { var setting = GetMergedSettings(sourceType, destinationType, mapType); var arg = new CompileArgument { SourceType = sourceType, DestinationType = destinationType, MapType = mapType, Context = context, Settings = setting, }; return(arg); }