comparison Extensions/JointureAddOn/Mapping/FullObjectMapper.cs @ 0:f990fcb411a9

Копия текущей версии из github
author cin
date Thu, 27 Mar 2014 21:46:09 +0400
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:f990fcb411a9
1 #region
2
3 using System;
4 using System.Collections;
5 using System.Collections.Generic;
6 using System.Linq;
7 using System.Reflection;
8 using BLToolkit.Data;
9 using BLToolkit.DataAccess;
10 using BLToolkit.Emit;
11 using BLToolkit.Reflection;
12 using BLToolkit.Reflection.Extension;
13
14 #endregion
15
16 namespace BLToolkit.Mapping
17 {
18 public class FullObjectMapper : ObjectMapper, IObjectMapper
19 {
20 #region Fields
21
22 private static readonly object SetterHandlersLock = new object();
23
24 private static readonly Dictionary<Type, Dictionary<string, SetHandler>> SettersHandlers =
25 new Dictionary<Type, Dictionary<string, SetHandler>>();
26
27 private static readonly Dictionary<Type, Dictionary<string, GetHandler>> GettersHandlers =
28 new Dictionary<Type, Dictionary<string, GetHandler>>();
29
30 private readonly DbManager _db;
31 private readonly FactoryType _factoryType;
32 private readonly bool _ignoreLazyLoad;
33
34 #endregion
35
36 public FullObjectMapper(DbManager db, bool ignoreLazyLoading, FactoryType factoryType)
37 {
38 _db = db;
39 _ignoreLazyLoad = ignoreLazyLoading;
40 _factoryType = factoryType;
41
42 PropertiesMapping = new List<IMapper>();
43 PrimaryKeyValueGetters = new List<GetHandler>();
44 PrimaryKeyNames = new List<string>();
45 }
46
47 #region IPropertiesMapping Members
48
49 public List<IMapper> PropertiesMapping { get; private set; }
50 public IPropertiesMapping ParentMapping { get; set; }
51
52 #endregion
53
54 public bool IsNullable { get; set; }
55 public bool ColParent { get; set; }
56
57 #region IMapper Members
58
59 public int DataReaderIndex { get; set; }
60 public SetHandler Setter { get; set; }
61 public Type PropertyType { get; set; }
62 public string PropertyName { get; set; }
63 public Association Association { get; set; }
64
65 #endregion
66
67 #region IObjectMapper
68
69 public bool IsLazy { get; set; }
70 public bool ContainsLazyChild { get; set; }
71 public GetHandler Getter { get; set; }
72
73 public List<string> PrimaryKeyNames { get; set; }
74
75 #endregion
76
77 #region ILazyMapper
78
79 public GetHandler ParentKeyGetter { get; set; }
80 public List<GetHandler> PrimaryKeyValueGetters { get; set; }
81
82 #endregion
83
84 #region Overrides
85
86 public override void Init(MappingSchema mappingSchema, Type type)
87 {
88 PropertyType = type;
89
90 // TODO implement this method
91 base.Init(mappingSchema, type);
92
93 int startIndex = 0;
94 GetObjectMapper(this, ref startIndex, _typeAccessor);
95 }
96
97 public override object CreateInstance()
98 {
99 object result = ContainsLazyChild
100 ? (_factoryType == FactoryType.LazyLoading
101 ? TypeFactory.LazyLoading.Create(PropertyType, this, LoadLazy)
102 : TypeFactory.LazyLoadingWithDataBinding.Create(PropertyType, this, LoadLazy))
103 : FunctionFactory.Remote.CreateInstance(PropertyType);
104
105 return result;
106 }
107
108 public override object CreateInstance(InitContext context)
109 {
110 return CreateInstance();
111 }
112
113 #endregion
114
115 #region Private methods
116
117 private TableDescription GetTableDescription(Type type)
118 {
119 var tableDescription = new TableDescription();
120 object[] tableAtt = type.GetCustomAttributes(typeof (TableNameAttribute), true);
121
122 if (tableAtt.Length > 0)
123 {
124 var tna = (TableNameAttribute) tableAtt[0];
125
126 tableDescription.Database = tna.Database;
127 tableDescription.Owner = tna.Owner;
128 tableDescription.TableName = tna.Name;
129 }
130
131 return tableDescription;
132 }
133
134 private IMapper GetObjectMapper(IObjectMapper mapper, ref int startIndex, TypeAccessor akTypeAccessor)
135 {
136 //Todo: Remove this Call!
137 _extension = TypeExtension.GetTypeExtension(mapper.PropertyType /*_typeAccessor.OriginalType*/, MappingSchema.Extensions);
138
139 Type mapperType = mapper.PropertyType;
140 var objectMappers = new List<IObjectMapper>();
141
142 TableDescription tableDescription = GetTableDescription(mapperType);
143
144 lock (SetterHandlersLock)
145 {
146 if (!SettersHandlers.ContainsKey(mapperType))
147 SettersHandlers.Add(mapperType, new Dictionary<string, SetHandler>());
148
149 if (!GettersHandlers.ContainsKey(mapperType))
150 GettersHandlers.Add(mapperType, new Dictionary<string, GetHandler>());
151 }
152
153 PropertyInfo[] properties = mapperType.GetProperties();
154
155 MemberAccessor primaryKeyMemberAccessor = null;
156 foreach (MemberAccessor ma in akTypeAccessor)
157 {
158 // Setters
159 lock (SetterHandlersLock)
160 {
161 if (!SettersHandlers[mapper.PropertyType].ContainsKey(ma.Name))
162 {
163 SettersHandlers[mapper.PropertyType].Add(ma.Name, ma.SetValue);
164 }
165 }
166
167 if (GetPrimaryKey(ma) != null)
168 {
169 primaryKeyMemberAccessor = ma;
170
171 lock (SetterHandlersLock)
172 {
173 if (!GettersHandlers[mapperType].ContainsKey(ma.Name))
174 {
175 GettersHandlers[mapperType].Add(ma.Name, ma.GetValue);
176 }
177 }
178 mapper.PrimaryKeyValueGetters.Add(GettersHandlers[mapperType][ma.Name]);
179 mapper.PrimaryKeyNames.Add(ma.Name);
180
181 if (mapper.Association != null && (mapper.Association.OtherKey == null || mapper.Association.OtherKey.Length == 0))
182 {
183 mapper.Association.OtherKey = new[] {ma.Name};
184 }
185 }
186 }
187 if (primaryKeyMemberAccessor == null)
188 throw new Exception("PrimaryKey attribute not found on type: " + mapperType);
189
190 foreach (PropertyInfo prop in properties)
191 {
192 var ma = akTypeAccessor.First(x => x.Name == prop.Name);
193
194 // Check if the accessor is an association
195 var association = GetAssociation(ma);
196 if (association != null)
197 {
198 // Getters for IObjectMapper
199 lock (SetterHandlersLock)
200 if (!GettersHandlers[mapperType].ContainsKey(prop.Name))
201 {
202 GettersHandlers[mapperType].Add(prop.Name, ma.GetValue);
203 }
204
205 bool isCollection = prop.PropertyType.GetInterfaces().ToList().Contains(typeof (IList));
206 IObjectMapper propertiesMapping;
207 if (!isCollection)
208 {
209 // TODO Generate this instance using the CreateObjectMapperInstance method of fullMappingSchema
210 // _db.MappingSchema.CreateObjectMapperInstance(prop.PropertyType)
211
212 propertiesMapping = new FullObjectMapper(_db, _ignoreLazyLoad, _factoryType)
213 {
214 PropertyType = prop.PropertyType,
215 IsNullable = association.CanBeNull,
216 Getter = GettersHandlers[mapperType][prop.Name],
217 };
218 }
219 else
220 {
221 Type listElementType = GetGenericType(prop.PropertyType);
222 TableDescription colElementTableDescription = GetTableDescription(listElementType);
223
224 // TODO Generate this instance using the CreateObjectMapperInstance method of fullMappingSchema
225 propertiesMapping = new CollectionFullObjectMapper(_db, _factoryType)
226 {
227 PropertyType = listElementType,
228 Getter = GettersHandlers[mapperType][prop.Name],
229 TableName = colElementTableDescription.TableName,
230 PropertyCollectionType = prop.PropertyType,
231 };
232
233 if (mapper is FullObjectMapper)
234 ((FullObjectMapper) mapper).ColParent = true;
235 }
236
237 if (association.ThisKey == null || association.ThisKey.Length == 0)
238 association.ThisKey = new[] {primaryKeyMemberAccessor.Name};
239
240 bool isLazy = false;
241 if (!_ignoreLazyLoad)
242 {
243 var lazy = GetLazyInstance(ma); // prop.GetCustomAttributes(typeof(LazyInstanceAttribute), true);
244 if (lazy)
245 {
246 isLazy = true;
247 mapper.ContainsLazyChild = true;
248
249 // Getters
250 lock (SetterHandlersLock)
251 if (!GettersHandlers[mapperType].ContainsKey(primaryKeyMemberAccessor.Name))
252 {
253 GettersHandlers[mapperType].Add(primaryKeyMemberAccessor.Name, primaryKeyMemberAccessor.GetValue);
254 }
255 }
256 }
257
258 propertiesMapping.Association = association;
259 propertiesMapping.PropertyName = prop.Name;
260 propertiesMapping.IsLazy = isLazy;
261 propertiesMapping.Setter = SettersHandlers[mapperType][prop.Name];
262
263 if (propertiesMapping.IsLazy)
264 {
265 propertiesMapping.ParentKeyGetter = GettersHandlers[mapperType][primaryKeyMemberAccessor.Name];
266 }
267 objectMappers.Add(propertiesMapping);
268 }
269 else
270 {
271 var mapIgnore = GetMapIgnore(ma);
272 if (mapIgnore)
273 continue;
274
275 var mapField = GetMapField(ma);
276 string columnName = mapField != null ? mapField.MapName : prop.Name;
277
278 var map = new ValueMapper
279 {
280 PropertyName = prop.Name,
281 PropertyType = prop.PropertyType,
282 DataReaderIndex = startIndex,
283 Setter = SettersHandlers[mapperType][prop.Name],
284 TableName = tableDescription.TableName,
285 ColumnName = columnName,
286 };
287
288 var mapColumnName = map.GetColumnName(columnName);
289 map.ColumnAlias = columnName == mapColumnName ? null : mapColumnName;
290
291 mapper.PropertiesMapping.Add(map);
292
293 var pkField = GetPrimaryKey(ma);
294 if (pkField != null)
295 mapper.DataReaderIndex = startIndex;
296
297 startIndex++;
298 }
299 }
300
301 foreach (IObjectMapper objMap in objectMappers)
302 {
303 #region Check mapping recursion
304
305 IObjectMapper cel = mapper;
306 while (cel != null)
307 {
308 if (mapper.PropertyType == objMap.PropertyType)
309 continue;
310
311 cel = (IObjectMapper) cel.ParentMapping;
312 }
313
314 #endregion
315
316 objMap.ParentMapping = mapper;
317 mapper.PropertiesMapping.Add(GetObjectMapper(objMap, ref startIndex, MappingSchema.GetObjectMapper(objMap.PropertyType).TypeAccessor));
318 }
319
320 return mapper;
321 }
322
323 protected object LoadLazy(IMapper mapper, object proxy, Type parentType)
324 {
325 var lazyMapper = (ILazyMapper) mapper;
326 object key = lazyMapper.ParentKeyGetter(proxy);
327
328 var fullSqlQuery = new FullSqlQuery(_db, ignoreLazyLoad: true);
329 object parentLoadFull = fullSqlQuery.SelectByKey(parentType, key);
330 if (parentLoadFull == null)
331 {
332 object value = Activator.CreateInstance(mapper is CollectionFullObjectMapper
333 ? (mapper as CollectionFullObjectMapper).PropertyCollectionType
334 : mapper.PropertyType);
335 return value;
336 }
337
338 var objectMapper = (IObjectMapper) mapper;
339 return objectMapper.Getter(parentLoadFull);
340 }
341
342 private static Type GetGenericType(Type t)
343 {
344 if (t.IsGenericType)
345 {
346 Type[] at = t.GetGenericArguments();
347 return at.FirstOrDefault();
348 }
349 return null;
350 }
351
352 #endregion
353 }
354 }