annotate Source/Mapping/ExpressionMapper.cs @ 4:f757da6161a1

!bug 100 + 2h fixed gregression
author cin
date Sun, 24 Aug 2014 17:57:42 +0400
parents f990fcb411a9
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
0
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
1 using System;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
2 using System.Collections;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
3 using System.Collections.Generic;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
4 using System.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
5 using System.Linq.Expressions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
6 using System.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
7
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
8 using BLToolkit.Common;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
9 using BLToolkit.Data.Linq;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
10 using BLToolkit.Reflection;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
11
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
12 using JetBrains.Annotations;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
13
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
14 namespace BLToolkit.Mapping
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
15 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
16 class Mapper<TS,TD>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
17 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
18 public Func<TS,MappingContext,TD> Map;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
19 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
20
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
21 class MappingContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
22 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
23 public Dictionary<object,object> Objects;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
24 public Func<object,object> GetParent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
25 public List<Action<object>> CrossActions;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
26 public Dictionary<object,List<Action<object,object>>> Crosses;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
27 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
28
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
29 class MappingParameters
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
30 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
31 public MappingSchema MappingSchema;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
32 public bool DeepCopy = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
33 public bool HandleCrossReferences = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
34 public bool IncludeComplexMapping;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
35
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
36 public Dictionary<object,object> MapperList = new Dictionary<object,object>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
37
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
38 public bool UseContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
39 public bool ContextParameterUsed;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
40
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
41 readonly ParameterExpression _mappingContext = Expression.Parameter(typeof(MappingContext), "ctx");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
42 public ParameterExpression MappingContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
43 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
44 get
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
45 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
46 ContextParameterUsed = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
47 return _mappingContext;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
48 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
49 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
50 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
51
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
52 public class ExpressionMapper<TSource,TDest>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
53 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
54 readonly MappingParameters _parameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
55 private Func<object,object> _getCurrent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
56 private Action<object,object> _setCurrent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
57
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
58 public bool DeepCopy { get { return _parameters.DeepCopy; } set { _parameters.DeepCopy = value; } }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
59 public bool HandleBackReferences { get { return _parameters.HandleCrossReferences; } set { _parameters.HandleCrossReferences = value; } }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
60 public bool IncludeComplexMapping { get { return _parameters.IncludeComplexMapping; } set { _parameters.IncludeComplexMapping = value; } }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
61
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
62 public ExpressionMapper()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
63 : this(Map.DefaultSchema)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
64 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
65 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
66
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
67 public ExpressionMapper(MappingSchema mappingSchema)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
68 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
69 _parameters = new MappingParameters { MappingSchema = mappingSchema };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
70 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
71
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
72 ExpressionMapper(MappingParameters parameters)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
73 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
74 _parameters = parameters;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
75 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
76
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
77 #region Value Converter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
78
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
79 interface IValueConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
80 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
81 Expression GetConverter (Expression source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
82 Expression CheckNull (ExpressionMapper<TSource,TDest> mapper, Expression source, object nullValue, MapValue[] mapValues, object defaultValue, MapValue[] srcMapValues);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
83 Expression SourceMapValues(ExpressionMapper<TSource,TDest> mapper, Expression source, object nullValue, object defaultValue, MapValue[] srcMapValues);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
84 Expression DestMapValues (ExpressionMapper<TSource,TDest> mapper, Expression source, object nullValue, MapValue[] mapValues, object defaultValue);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
85 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
86
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
87 class ValueConvertHelper<TS,TD> : IValueConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
88 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
89 public Expression GetConverter(Expression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
90 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
91 return Expression.Invoke(Expression.Constant(Convert<TD,TS>.From), source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
92 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
93
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
94 public Expression CheckNull(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
95 ExpressionMapper<TSource,TDest> mapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
96 Expression source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
97 object nullValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
98 MapValue[] mapValues,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
99 object defaultValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
100 MapValue[] srcMapValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
101 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
102 var param =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
103 source.NodeType != ExpressionType.MemberAccess &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
104 source.NodeType != ExpressionType.Parameter &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
105 source.NodeType != ExpressionType.Constant?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
106 Expression.Parameter(typeof(TS), "p") :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
107 null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
108
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
109 var nexpr = Expression.Constant(nullValue ?? default(TD));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
110
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
111 var expr =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
112 source.NodeType == ExpressionType.Constant && ((ConstantExpression)source).Value == null ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
113 nexpr as Expression:
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
114 Expression.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
115 Expression.Equal(param ?? source, Expression.Constant(null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
116 nexpr.Value == null ? Expression.Convert(nexpr, typeof(TD)) : nexpr as Expression,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
117 mapper.GetValueMapper(param ?? source, typeof(TD), false, null, mapValues, defaultValue, srcMapValues));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
118
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
119 return param == null ? expr : Expression.Invoke(Expression.Lambda<Func<TS,TD>>(expr, param), source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
120 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
121
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
122 public Expression SourceMapValues(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
123 ExpressionMapper<TSource,TDest> mapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
124 Expression source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
125 object nullValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
126 object defaultValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
127 MapValue[] srcMapValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
128 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
129 var param =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
130 //source.NodeType != ExpressionType.MemberAccess &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
131 source.NodeType != ExpressionType.Parameter &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
132 source.NodeType != ExpressionType.Constant?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
133 Expression.Parameter(typeof(TS), "p") :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
134 null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
135
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
136 var expr = mapper.GetValueMapper(Expression.Constant(defaultValue), typeof(TD), true, nullValue, null, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
137
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
138 for (var i = srcMapValues.Length - 1; i >= 0; i--)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
139 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
140 var value = srcMapValues[i];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
141
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
142 expr = Expression.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
143 Expression.Equal(param ?? source, mapper.GetValueMapper(Expression.Constant(value.OrigValue), typeof(TS), false, null, null, null, null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
144 mapper.GetValueMapper(Expression.Constant(value.MapValues[0]), typeof(TD), true, nullValue, null, null, null),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
145 expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
146 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
147
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
148 return param == null ? expr : Expression.Invoke(Expression.Lambda<Func<TS,TD>>(expr, param), source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
149 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
150
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
151 public Expression DestMapValues(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
152 ExpressionMapper<TSource,TDest> mapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
153 Expression source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
154 object nullValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
155 MapValue[] mapValues,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
156 object defaultValue)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
157 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
158 var param =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
159 //source.NodeType != ExpressionType.MemberAccess &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
160 source.NodeType != ExpressionType.Parameter &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
161 source.NodeType != ExpressionType.Constant?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
162 Expression.Parameter(typeof(TS), "p") :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
163 null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
164
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
165 var expr = mapper.GetValueMapper(Expression.Constant(defaultValue), typeof(TD), true, nullValue, null, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
166
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
167 for (var i = mapValues.Length - 1; i >= 0; i--)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
168 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
169 var value = mapValues[i];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
170 var orex = null as Expression;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
171
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
172 foreach (var mapValue in value.MapValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
173 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
174 var ex = Expression.Equal(param ?? source, mapper.GetValueMapper(Expression.Constant(mapValue), typeof (TS), false, null, null, null, null));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
175 orex = orex == null ? ex : Expression.OrElse(orex, ex);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
176 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
177
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
178 if (orex != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
179 expr = Expression.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
180 orex,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
181 mapper.GetValueMapper(Expression.Constant(value.OrigValue), typeof(TD), true, nullValue, null, null, null),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
182 expr);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
183 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
184
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
185 return param == null ? expr : Expression.Invoke(Expression.Lambda<Func<TS,TD>>(expr, param), source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
186 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
187 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
188
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
189 static IValueConvertHelper GetValueHelper(Type stype, Type dtype)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
190 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
191 var type = typeof(ValueConvertHelper<,>).MakeGenericType(typeof(TSource), typeof(TDest), stype, dtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
192 return ((IValueConvertHelper)Activator.CreateInstance(type));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
193 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
194
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
195 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
196
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
197 #region Object Converter
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
198
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
199 interface IConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
200 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
201 Expression MapObjects(ExpressionMapper<TSource,TDest> mapper, Expression source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
202 Expression MapLists (ExpressionMapper<TSource,TDest> mapper, Expression source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
203 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
204
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
205 class ConvertHelper<TS,TD> : IConvertHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
206 where TS : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
207 where TD : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
208 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
209 static TD MapCrossReferences(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
210 MappingContext ctx,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
211 TS source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
212 Func<TS,TD> func,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
213 Func<object,object> getCurrent,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
214 Action<object,object> setCurrent)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
215 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
216 if (source == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
217 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
218
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
219 object dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
220 List<Action<object,object>> list;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
221
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
222 if (ctx.Objects.TryGetValue(source, out dest))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
223 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
224 if (dest == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
225 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
226 if (ctx.Crosses == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
227 ctx.Crosses = new Dictionary<object,List<Action<object,object>>>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
228
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
229 if (!ctx.Crosses.TryGetValue(source, out list))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
230 ctx.Crosses[source] = list = new List<Action<object,object>>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
231
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
232 var getParent = ctx.GetParent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
233
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
234 Action<object,object> setter = (obj,value) => setCurrent(getParent(obj), value);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
235
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
236 list.Add(setter);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
237 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
238
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
239 return (TD)dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
240 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
241
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
242 var currParent = ctx.GetParent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
243
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
244 ctx.GetParent = p => getCurrent(currParent(p));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
245 ctx.Objects.Add(source, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
246 ctx.Objects[source] = dest = func(source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
247 ctx.GetParent = currParent;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
248
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
249 if (ctx.Crosses != null && ctx.Crosses.TryGetValue(source, out list))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
250 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
251 if (ctx.CrossActions == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
252 ctx.CrossActions = new List<Action<object>>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
253
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
254 foreach (var action in list)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
255 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
256 var setValue = action;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
257
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
258 Action<object> f = parent => setValue(parent, dest);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
259 ctx.CrossActions.Add(f);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
260 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
261
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
262 ctx.Crosses.Remove(source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
263 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
264
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
265 return (TD)dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
266 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
267
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
268 static TD MapObjects(TS source, Func<TS,TD> func)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
269 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
270 return source == null ? null : func(source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
271 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
272
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
273 public Expression MapObjects(ExpressionMapper<TSource,TDest> mapper, Expression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
274 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
275 var param = mapper._getCurrent == null ? (ParameterExpression)source : Expression.Parameter(source.Type, "source");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
276
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
277 Expression expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
278 object m;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
279
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
280 if (mapper._parameters.MapperList.TryGetValue(new { S = typeof(TS), D = typeof(TD) }, out m))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
281 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
282 var map = (Mapper<TS,TD>)m;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
283
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
284 if (map.Map == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
285 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
286 expr = Expression.Invoke(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
287 Expression.PropertyOrField(Expression.Constant(map), "Map"),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
288 source, mapper._parameters.MappingContext);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
289 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
290 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
291 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
292 expr = Expression.Invoke(Expression.Constant(map.Map), source, mapper._parameters.MappingContext);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
293 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
294 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
295 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
296 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
297 var exmap = new ExpressionMapper<TS,TD>(mapper._parameters);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
298 expr = exmap.GetMemberInit(param);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
299 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
300
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
301 if (mapper._getCurrent == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
302 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
303
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
304 if (!mapper.HandleBackReferences)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
305 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
306 Expression<Func<object>> func = () => MapObjects((TS)null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
307 return Expression.Call((MethodInfo)ReflectionHelper.MemeberInfo(func), source, Expression.Lambda<Func<TS,TD>>(expr, param));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
308 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
309 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
310 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
311 mapper._parameters.UseContext = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
312
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
313 Expression<Func<object>> func = () => MapCrossReferences(null, null, null, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
314
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
315 return Expression.Call(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
316 (MethodInfo)ReflectionHelper.MemeberInfo(func),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
317 mapper._parameters.MappingContext,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
318 source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
319 Expression.Lambda<Func<TS,TD>>(expr, param),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
320 Expression.Constant(mapper._getCurrent),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
321 Expression.Constant(mapper._setCurrent));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
322 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
323 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
324
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
325 interface IItemHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
326 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
327 Expression MapLists(ExpressionMapper<TSource,TDest> mapper, Expression source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
328 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
329
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
330 interface IClassItemHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
331 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
332 MethodInfo GetObjectArrayInfo();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
333 MethodInfo GetObjectListInfo(bool isList);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
334 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
335
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
336 class ClassItemHelper<TSourceItem,TDestItem> : IClassItemHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
337 where TSourceItem : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
338 where TDestItem : class
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
339 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
340 static TDestItem[] MapObjectArray(MappingContext ctx, IEnumerable<TSourceItem> source, Func<TSourceItem,TDestItem> itemMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
341 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
342 if (source == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
343 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
344
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
345 if (source is ICollection)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
346 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
347 var col = (ICollection)source;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
348 var dest = new TDestItem[col.Count];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
349 var n = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
350
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
351 foreach (var item in source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
352 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
353 var current = n;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
354 dest[n++] = ConvertHelper<TSourceItem,TDestItem>.MapCrossReferences(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
355 ctx, item, itemMapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
356 _ => dest[current],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
357 (_,v) => { dest[current] = (TDestItem)v; });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
358 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
359
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
360 return dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
361 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
362 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
363 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
364 TDestItem[] dest = null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
365
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
366 var list = new List<TDestItem>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
367 var n = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
368
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
369 foreach (var item in source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
370 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
371 var current = n;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
372 list.Add(null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
373 list[n++] = ConvertHelper<TSourceItem,TDestItem>.MapCrossReferences(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
374 ctx, item, itemMapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
375 _ => dest == null ? list[current] : dest[current],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
376 (_,v) => { if (dest == null) list[current] = (TDestItem)v; else dest[current] = (TDestItem)v; });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
377 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
378
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
379 return dest = list.ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
380 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
381 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
382
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
383 [UsedImplicitly]
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
384 static TList MapObjectList<TList>(MappingContext ctx, IEnumerable<TSourceItem> source, Func<TSourceItem,TDestItem> itemMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
385 where TList : class, IList<TDestItem>, new()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
386 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
387 if (source == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
388 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
389
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
390 var n = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
391 var dest = source is ICollection && typeof(TList) == typeof(List<TDestItem>) ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
392 (TList)(IList<TDestItem>)new List<TDestItem>(((ICollection)source).Count) : new TList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
393
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
394 foreach (var item in source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
395 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
396 var current = n;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
397 dest.Add(null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
398 dest[n++] = ConvertHelper<TSourceItem,TDestItem>.MapCrossReferences(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
399 ctx, item, itemMapper,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
400 _ => dest[current],
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
401 (_,v) => { dest[current] = (TDestItem)v; });
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
402 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
403
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
404 return dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
405 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
406
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
407 public MethodInfo GetObjectArrayInfo()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
408 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
409 Expression<Func<object>> arrMapper = () => MapObjectArray(null, null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
410 return (MethodInfo)ReflectionHelper.MemeberInfo(arrMapper);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
411 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
412
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
413 public MethodInfo GetObjectListInfo(bool isList)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
414 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
415 var method = typeof(ClassItemHelper<TSourceItem,TDestItem>).GetMethod("MapObjectList", BindingFlags.NonPublic | BindingFlags.Static);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
416 return method.MakeGenericMethod(isList ? typeof (List<TDestItem>) : typeof (TD));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
417 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
418 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
419
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
420 class ItemHelper<TSourceItem,TDestItem> : IItemHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
421 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
422 static TDestItem[] MapScalarArray(IEnumerable<TSourceItem> source, Func<TSourceItem,TDestItem> itemMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
423 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
424 if (source == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
425 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
426
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
427 if (source is ICollection)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
428 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
429 var col = (ICollection)source;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
430 var dest = new TDestItem[col.Count];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
431 var n = 0;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
432
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
433 foreach (var item in source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
434 dest[n++] = itemMapper(item);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
435
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
436 return dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
437 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
438
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
439 return source.Select(itemMapper).ToArray();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
440 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
441
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
442 [UsedImplicitly]
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
443 static TList MapScalarList<TList>(IEnumerable<TSourceItem> source, Func<TSourceItem,TDestItem> itemMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
444 where TList : class, IList<TDestItem>, new()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
445 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
446 if (source == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
447 return null;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
448
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
449 var dest = new TList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
450 var list = dest as List<TDestItem>;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
451
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
452 if (list != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
453 list.AddRange(source.Select(itemMapper));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
454 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
455 foreach (var item in source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
456 dest.Add(itemMapper(item));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
457
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
458 return dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
459 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
460
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
461 public Expression MapLists(ExpressionMapper<TSource,TDest> mapper, Expression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
462 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
463 var itemMapper =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
464 new ExpressionMapper<TSourceItem,TDestItem>(mapper._parameters);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
465
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
466 var itemParam = Expression.Parameter(typeof(TSourceItem), "item");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
467 var itemExpr = itemMapper.GetValueMapper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
468 itemParam,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
469 typeof(TDestItem),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
470 true,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
471 mapper._parameters.MappingSchema.GetNullValue (typeof(TDestItem)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
472 mapper._parameters.MappingSchema.GetMapValues (typeof(TDestItem)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
473 mapper._parameters.MappingSchema.GetDefaultValue(typeof(TDestItem)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
474 mapper._parameters.MappingSchema.GetMapValues (typeof(TSourceItem)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
475
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
476 var itemLambda = Expression.Lambda<Func<TSourceItem,TDestItem>>(itemExpr, itemParam);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
477
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
478 var isSourceScalar = !typeof(TSourceItem).IsArray && TypeHelper.IsScalar(typeof(TSourceItem));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
479 var isDestScalar = !typeof(TDestItem). IsArray && TypeHelper.IsScalar(typeof(TDestItem));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
480
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
481 if (!mapper.HandleBackReferences || isSourceScalar || isDestScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
482 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
483 if (typeof (TD).IsArray)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
484 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
485 Expression<Func<object>> arrMapper = () => MapScalarArray(null, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
486 return Expression.Call((MethodInfo)ReflectionHelper.MemeberInfo(arrMapper), source, itemLambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
487 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
488
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
489 var isList =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
490 typeof (TD) == typeof (IEnumerable<TDestItem>) || typeof (TD) == typeof (ICollection<TDestItem>) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
491 typeof (TD) == typeof (IList<TDestItem>) || typeof (TD) == typeof (List<TDestItem>);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
492
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
493 var method = typeof (ItemHelper<TSourceItem, TDestItem>).GetMethod("MapScalarList", BindingFlags.NonPublic | BindingFlags.Static);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
494
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
495 method = method.MakeGenericMethod(isList ? typeof (List<TDestItem>) : typeof (TD));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
496
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
497 return Expression.Call(method, source, itemLambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
498 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
499 else
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
500 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
501 mapper._parameters.UseContext = true;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
502
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
503 var type = typeof (ClassItemHelper<,>).MakeGenericType(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
504 typeof (TSource), typeof (TDest),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
505 typeof (TS), typeof (TD),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
506 typeof (TSourceItem), typeof (TDestItem));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
507
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
508 var helper = ((IClassItemHelper)Activator.CreateInstance(type));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
509
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
510 if (typeof (TD).IsArray)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
511 return Expression.Call(helper.GetObjectArrayInfo(), mapper._parameters.MappingContext, source, itemLambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
512
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
513 var isList =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
514 typeof (TD) == typeof (IEnumerable<TDestItem>) || typeof (TD) == typeof (ICollection<TDestItem>) ||
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
515 typeof (TD) == typeof (IList<TDestItem>) || typeof (TD) == typeof (List<TDestItem>);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
516
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
517 return Expression.Call(helper.GetObjectListInfo(isList), mapper._parameters.MappingContext, source, itemLambda);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
518 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
519 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
520 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
521
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
522 public Expression MapLists(ExpressionMapper<TSource,TDest> mapper, Expression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
523 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
524 var ts = TypeHelper.GetGenericType(typeof(IEnumerable<>), typeof(TS)).GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
525 var td = TypeHelper.GetGenericType(typeof(IEnumerable<>), typeof(TD)).GetGenericArguments()[0];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
526
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
527 var type = typeof(ItemHelper<,>).MakeGenericType(typeof(TSource), typeof(TDest), typeof(TS), typeof(TD), ts, td);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
528 return ((IItemHelper)Activator.CreateInstance(type)).MapLists(mapper, source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
529 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
530 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
531
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
532 static IConvertHelper GetHelper(Type stype, Type dtype)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
533 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
534 var type = typeof(ConvertHelper<,>).MakeGenericType(typeof(TSource), typeof(TDest), stype, dtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
535 return ((IConvertHelper)Activator.CreateInstance(type));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
536 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
537
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
538 #endregion
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
539
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
540 Expression GetValueMapper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
541 Expression source,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
542 Type dtype,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
543 bool checkNull,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
544 object nullValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
545 MapValue[] destMapValues,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
546 object defaultValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
547 MapValue[] srcMapValues)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
548 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
549 var stype = source.Type;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
550
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
551 var isSourceScalar = !stype.IsArray && TypeHelper.IsScalar(stype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
552 var isDestScalar = !dtype.IsArray && TypeHelper.IsScalar(dtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
553
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
554 if (dtype == typeof(object) || dtype == stype && (!DeepCopy || isSourceScalar))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
555 return source;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
556
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
557 var isSourceNullable = TypeHelper.IsNullableType(stype) || stype.IsClass;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
558
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
559 if (checkNull && isSourceNullable && !TypeHelper.IsNullableType(dtype) && (isDestScalar || isSourceScalar))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
560 return GetValueHelper(stype, dtype).CheckNull(this, source, nullValue, destMapValues, defaultValue, srcMapValues);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
561
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
562 if (srcMapValues != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
563 return GetValueHelper(stype, dtype).SourceMapValues(this, source, nullValue, defaultValue, srcMapValues);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
564
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
565 if (destMapValues != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
566 return GetValueHelper(stype, dtype).DestMapValues(this, source, nullValue, destMapValues, defaultValue);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
567
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
568 if (dtype == typeof (string))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
569 return
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
570 isSourceNullable
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
571 ?
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
572 Expression.Condition(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
573 Expression.Equal(source, Expression.Constant(null)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
574 Expression.Constant(null),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
575 Expression.Call(source, "ToString", Array<Type>.Empty)) as Expression
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
576 :
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
577 Expression.Call(source, "ToString", Array<Type>.Empty);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
578
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
579 if (!isDestScalar && !isSourceScalar)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
580 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
581 if (TypeHelper.GetGenericType(typeof(IEnumerable<>), dtype) != null &&
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
582 TypeHelper.GetGenericType(typeof(IEnumerable<>), stype) != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
583 return GetHelper(stype, dtype).MapLists(this, source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
584
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
585 return GetHelper(stype, dtype).MapObjects(this, source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
586 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
587
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
588 try
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
589 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
590 return Expression.Convert(source, dtype);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
591 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
592 catch (InvalidOperationException)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
593 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
594 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
595
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
596 return GetValueHelper(stype, dtype).GetConverter(source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
597 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
598
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
599 IEnumerable<MemberBinding> GetBindings(Expression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
600 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
601 var dest = _parameters.MappingSchema.GetObjectMapper(typeof(TDest));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
602 var src = _parameters.MappingSchema.GetObjectMapper(typeof(TSource));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
603
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
604 foreach (MemberMapper dmm in dest)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
605 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
606 if (!IncludeComplexMapping && dmm is MemberMapper.ComplexMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
607 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
608
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
609 var dma = dmm.MemberAccessor;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
610
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
611 if (!dma.HasSetter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
612 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
613
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
614 var attr = dma.GetAttribute<ExpressionMapIgnoreAttribute>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
615
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
616 if (attr != null && attr.Ignore)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
617 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
618
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
619 var smm = src[dmm.Name];
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
620
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
621 if (smm == null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
622 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
623
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
624 if (!IncludeComplexMapping && smm is MemberMapper.ComplexMapper)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
625 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
626
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
627 var sma = smm.MemberAccessor;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
628
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
629 if (!sma.HasGetter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
630 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
631
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
632 attr = sma.GetAttribute<ExpressionMapIgnoreAttribute>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
633
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
634 if (attr != null && attr.Ignore)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
635 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
636
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
637 _getCurrent = dma.GetValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
638 _setCurrent = dma.SetValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
639
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
640 var bind = Expression.Bind(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
641 dma.MemberInfo,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
642 GetValueMapper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
643 Expression.PropertyOrField(source, sma.Name),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
644 dma.Type,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
645 true,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
646 dmm.MapMemberInfo.NullValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
647 dmm.MapMemberInfo.MapValues,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
648 dmm.MapMemberInfo.DefaultValue,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
649 smm.MapMemberInfo.MapValues));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
650
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
651 yield return bind;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
652 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
653
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
654 var destMembers = from m in ((IEnumerable<MemberAccessor>)dest.TypeAccessor) select m;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
655
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
656 destMembers = destMembers.Except(dest.Select(mm => mm.MemberAccessor)).ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
657
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
658 var srcMembers =
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
659 (from m in ((IEnumerable<MemberAccessor>)src.TypeAccessor) select m)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
660 .Except(src.Select(mm => mm.MemberAccessor))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
661 .ToList();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
662
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
663 foreach (var dma in destMembers)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
664 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
665 if (!dma.HasSetter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
666 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
667
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
668 var sma = srcMembers.FirstOrDefault(mi => mi.Name == dma.Name);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
669
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
670 if (sma == null || !sma.HasGetter)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
671 continue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
672
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
673 _getCurrent = dma.GetValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
674 _setCurrent = dma.SetValue;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
675
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
676 var bind = Expression.Bind(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
677 dma.MemberInfo,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
678 GetValueMapper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
679 Expression.MakeMemberAccess(source, sma.MemberInfo),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
680 dma.Type,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
681 true,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
682 _parameters.MappingSchema.GetNullValue (dma.Type),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
683 _parameters.MappingSchema.GetMapValues (dma.Type),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
684 _parameters.MappingSchema.GetDefaultValue(dma.Type),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
685 _parameters.MappingSchema.GetMapValues (sma.Type)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
686
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
687 yield return bind;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
688 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
689 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
690
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
691 Expression GetMemberInit(ParameterExpression source)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
692 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
693 var mapper = new Mapper<TSource,TDest>();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
694
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
695 _parameters.MapperList.Add(new { S = typeof(TSource), D = typeof(TDest) }, mapper);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
696
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
697 var dest = TypeAccessor<TDest>.Instance;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
698 var expr = Expression.MemberInit(Expression.New(dest.Type), GetBindings(source));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
699
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
700 mapper.Map = Expression.Lambda<Func<TSource,MappingContext,TDest>>(expr, source, _parameters.MappingContext).Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
701
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
702 return expr;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
703 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
704
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
705 interface IAbstractHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
706 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
707 Func<TSource,TDest> GetMapper(MappingParameters ps);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
708 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
709
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
710 class AbstractHelper<TS,TD> : IAbstractHelper
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
711 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
712 public Func<TSource,TDest> GetMapper(MappingParameters ps)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
713 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
714 var em = new ExpressionMapper<TS,TD>(ps);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
715 var mapper = em.GetMapper();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
716
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
717 return source => (TDest)(object)mapper((TS)(object)source);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
718 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
719 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
720
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
721 public Func<TSource,TDest> GetMapper()
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
722 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
723 if (typeof(TSource) == typeof(TDest) && !DeepCopy)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
724 return s => (TDest)(object)s;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
725
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
726 if (TypeHelper.IsAbstractClass(typeof(TSource)) || TypeHelper.IsAbstractClass(typeof(TDest)))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
727 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
728 var st = TypeHelper.IsAbstractClass(typeof(TSource)) ? TypeAccessor<TSource>.Instance.Type : typeof(TSource);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
729 var dt = TypeHelper.IsAbstractClass(typeof(TDest)) ? TypeAccessor<TDest>. Instance.Type : typeof(TDest);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
730
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
731 var type = typeof(AbstractHelper<,>).MakeGenericType(typeof(TSource), typeof(TDest), st, dt);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
732 return ((IAbstractHelper)Activator.CreateInstance(type)).GetMapper(_parameters);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
733 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
734
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
735 var parm = Expression.Parameter(typeof(TSource), "src");
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
736 var expr = GetValueMapper(
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
737 parm,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
738 typeof(TDest),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
739 true,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
740 _parameters.MappingSchema.GetNullValue (typeof(TDest)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
741 _parameters.MappingSchema.GetMapValues (typeof(TDest)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
742 _parameters.MappingSchema.GetDefaultValue(typeof(TDest)),
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
743 _parameters.MappingSchema.GetMapValues (typeof(TSource)));
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
744
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
745 if (_parameters.ContextParameterUsed)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
746 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
747 var l = Expression.Lambda<Func<TSource,MappingContext,TDest>>(expr, parm, _parameters.MappingContext);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
748 var f = l.Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
749
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
750 if (!_parameters.UseContext)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
751 return s => f(s, null);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
752
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
753 return s =>
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
754 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
755 var ctx = new MappingContext
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
756 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
757 Objects = new Dictionary<object,object>(10) { { s, null } },
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
758 GetParent = p => p,
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
759 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
760
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
761 var dest = f(s, ctx);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
762
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
763 if (ctx.CrossActions != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
764 foreach (var circle in ctx.CrossActions)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
765 circle(dest);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
766
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
767 if (ctx.Crosses != null)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
768 {
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
769 List<Action<object,object>> list;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
770
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
771 if (ctx.Crosses.TryGetValue(s, out list))
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
772 foreach (var action in list)
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
773 action(dest, dest);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
774 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
775
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
776 return dest;
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
777 };
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
778 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
779
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
780 var lambda = Expression.Lambda<Func<TSource,TDest>>(expr, parm);
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
781
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
782 return lambda.Compile();
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
783 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
784 }
f990fcb411a9 Копия текущей версии из github
cin
parents:
diff changeset
785 }