Datei: NDOEnhancer/Enhancer/Nodes/ClassNode.cs
Last Commit (006a7c7)
1 | // |
2 | // Copyright (c) 2002-2016 Mirko Matytschak |
3 | // (www.netdataobjects.de) |
4 | // |
5 | // Author: Mirko Matytschak |
6 | // |
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
8 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation |
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the |
10 | // Software, and to permit persons to whom the Software is furnished to do so, subject to the following |
11 | // conditions: |
12 | |
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions |
14 | // of the Software. |
15 | // |
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | // DEALINGS IN THE SOFTWARE. |
21 | |
22 | |
23 | using System; |
24 | using System.Diagnostics; |
25 | using System.Reflection; |
26 | using System.Collections; |
27 | using System.Collections.Generic; |
28 | using System.Linq; |
29 | using NDO; |
30 | using NDO.Mapping; |
31 | using NDO.Mapping.Attributes; |
32 | |
33 | namespace NDOEnhancer |
34 | { |
35 | ····/// <summary> |
36 | ····/// Zusammenfassung für ClassNode. |
37 | ····/// </summary> |
38 | ····internal class ClassNode |
39 | ····{ |
40 | ········string name = null; |
41 | ········List<FieldNode> fields = new List<FieldNode>(); |
42 | ········List<RelationNode> relations = new List<RelationNode>(); |
43 | ········List<EmbeddedTypeNode> embeddedTypes = new List<EmbeddedTypeNode>(); |
44 | ········Class myClass = null; |
45 | ········Type classType; |
46 | ········NDOMapping mappings; |
47 | |
48 | ········public ClassNode(Type t, NDOMapping mappings) |
49 | ········{ |
50 | ············this.classType = t; |
51 | ············if (t.IsGenericType && !t.IsGenericTypeDefinition) |
52 | ················throw new InternalException(45, "ClassNode"); |
53 | ············this.mappings = mappings; |
54 | ············this.name = new ReflectedType(t).ILNameWithoutPrefix; |
55 | ············this.isInterface = t.IsInterface; |
56 | ············this.isPersistent = IsPersistentType(t); |
57 | |
58 | ············Type basetype = t.BaseType; |
59 | ············this.baseFullName = new ReflectedType(basetype).ILNameWithoutPrefix; |
60 | ············this.isAbstract = t.IsAbstract; |
61 | ············AnalyzeFields(); |
62 | ············CheckOidAttributes(); |
63 | ········} |
64 | |
65 | ········private bool IsPersistentType(Type t) |
66 | ········{ |
67 | ············return t.GetCustomAttributes(typeof(NDOPersistentAttribute), false).Length > 0; |
68 | ········} |
69 | |
70 | ········private void CheckOidAttributes() |
71 | ········{ |
72 | ············List<OidColumnAttribute> collectedAttributes = new List<OidColumnAttribute>(); |
73 | |
74 | ············object[] attributes = this.classType.GetCustomAttributes(typeof(OidColumnAttribute), true); |
75 | ············if (attributes.Length > 0) |
76 | ············{ |
77 | ················if (this.classType.GetCustomAttributes(typeof(NDOOidTypeAttribute), true).Length > 0) |
78 | ····················new MessageAdapter().WriteLine("Warning: Can't mix OidColumnAttribute and NDOOidTypeAttribute in type " + this.name + ". The NDOOidTypeAttribute is ignored."); |
79 | ················foreach (OidColumnAttribute ca in attributes) |
80 | ····················collectedAttributes.Add(ca); |
81 | ············} |
82 | ············else // Try to implement the old mapping |
83 | ············{ |
84 | ················// The attribute is collected from the first base class defining it |
85 | ················attributes = this.classType.GetCustomAttributes(typeof(NDOOidTypeAttribute), true); |
86 | ················if (attributes.Length > 0) |
87 | ····················collectedAttributes.Add(new OidColumnAttribute(((NDOOidTypeAttribute)attributes[0]).OidType)); |
88 | ············} |
89 | ········ |
90 | ············FieldMap fieldMap = new FieldMap(this.classType); |
91 | ············foreach (var de in fieldMap.PersistentFields) |
92 | ············{ |
93 | ················FieldInfo fi = de.Value as FieldInfo; |
94 | ················if (fi == null) |
95 | ····················continue; |
96 | #pragma warning disable 0618 |
97 | ················if (fi.GetCustomAttributes(typeof(NDOObjectIdAttribute), false).Length > 0) |
98 | ················{ |
99 | ····················OidColumnAttribute ca = new OidColumnAttribute(); |
100 | ····················ca.FieldName = fi.Name; |
101 | ····················collectedAttributes.Add(ca); |
102 | ················} |
103 | #pragma warning restore 0618 |
104 | ············} |
105 | |
106 | ············// If no attribute is assigned to the class, look for attributes assigned to the assembly |
107 | ············if (collectedAttributes.Count == 0) |
108 | ············{ |
109 | ················attributes = this.classType.Assembly.GetCustomAttributes(typeof(OidColumnAttribute), false); |
110 | ················foreach (OidColumnAttribute ca in attributes) |
111 | ················{ |
112 | ····················ca.IsAssemblyWideDefinition = true; |
113 | ····················collectedAttributes.Add( ca ); |
114 | ················} |
115 | ············} |
116 | ············if (collectedAttributes.Count == 0) |
117 | ············{ |
118 | ················attributes = this.classType.Assembly.GetCustomAttributes(typeof(NDOOidTypeAttribute), false); |
119 | ················// The old mapping only allowed 1 NDOOidAttribute, so let's take the first one found |
120 | ················if (attributes.Length > 0) |
121 | ····················collectedAttributes.Add( new OidColumnAttribute( ((NDOOidTypeAttribute)attributes[0]).OidType ) { IsAssemblyWideDefinition = true } ); |
122 | ············} |
123 | ············if (collectedAttributes.Count > 0) |
124 | ············{ |
125 | ················this.columnAttributes = new OidColumnAttribute[collectedAttributes.Count]; |
126 | ················collectedAttributes.CopyTo(this.columnAttributes, 0); |
127 | ············} |
128 | ········} |
129 | |
130 | ········private void AnalyzeFields() |
131 | ········{ |
132 | ············IList relations = new ArrayList(); |
133 | ············var fis = this.classType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(fi=>!fi.IsInitOnly); |
134 | ············foreach (FieldInfo fi in fis) |
135 | ············{ |
136 | ················string fname = fi.Name; |
137 | ················if (fname.StartsWith("_ndo")) |
138 | ····················continue; |
139 | ················if (fi.FieldType.IsSubclassOf(typeof(System.Delegate))) |
140 | ····················continue; |
141 | |
142 | ················object[] attributes = fi.GetCustomAttributes(false); |
143 | ················bool cont = false; |
144 | ················foreach (System.Attribute attr in attributes) |
145 | ················{ |
146 | ····················if (attr is NDOTransientAttribute) |
147 | ····················{ |
148 | ························cont = true; |
149 | ························break; |
150 | ····················} |
151 | ····················if (attr is NDORelationAttribute) |
152 | ····················{ |
153 | ························this.relations.Add(new RelationNode(fi, (NDORelationAttribute)attr, this)); |
154 | ························cont = true; |
155 | ························break; |
156 | ····················} |
157 | ················} |
158 | ················if (cont) continue; |
159 | |
160 | ················// Field type is persistent - assume relation with element multiplicity. |
161 | ················if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType)) |
162 | ················{ |
163 | ····················NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType, RelationInfo.Default); |
164 | ····················this.relations.Add(new RelationNode(fi, nra, this)); |
165 | ····················continue; |
166 | ················} |
167 | |
168 | ················// Field is a collection - assume that it is either a relation or a transient field. |
169 | ················if (GenericIListReflector.IsGenericIList(fi.FieldType)) |
170 | ················{ |
171 | ····················if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType.GetGenericArguments()[0])) |
172 | ····················{ |
173 | ························NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType.GetGenericArguments()[0], RelationInfo.Default); |
174 | ························this.relations.Add(new RelationNode(fi, nra, this)); |
175 | ····················} |
176 | ····················else |
177 | ····················{ |
178 | ························Console.WriteLine("Warning: The field " + this.name + "." + fi.Name + " is a generic collection to a nonpersistent type. NDO assumes, that this field is transient."); |
179 | ····················} |
180 | ····················continue; |
181 | ················} |
182 | |
183 | ················if (!fi.FieldType.IsGenericParameter && fi.FieldType.IsClass && fi.FieldType != typeof(string) && fi.FieldType != typeof(byte[])) |
184 | ················{ |
185 | ····················this.embeddedTypes.Add(new EmbeddedTypeNode(fi)); |
186 | ················} |
187 | ················else |
188 | ················{ |
189 | ····················FieldNode fn = new FieldNode(fi); |
190 | ····················this.fields.Add(fn); |
191 | ····················Type ft = fi.FieldType; |
192 | ····················if (ft.IsValueType && !ft.IsEnum && !StorableTypes.Contains(ft)) |
193 | ····················{ |
194 | ························ValueTypes.Instance.Add(new ValueTypeNode(ft)); |
195 | ····················} |
196 | ················} |
197 | ············} |
198 | |
199 | ············// If there is more than one relation to the same target type |
200 | ············// without relation name, assign a relation name automatically |
201 | ············foreach(var group in this.relations.GroupBy( r => r.RelatedType )) |
202 | ············{ |
203 | ················if (group.Count() < 2) |
204 | ····················continue; |
205 | ················int countWithoutName = 0; |
206 | ················foreach (var rel in group) |
207 | ················{ |
208 | ····················if (string.IsNullOrEmpty( rel.RelationName )) |
209 | ····················{ |
210 | ························if (countWithoutName > 0) |
211 | ························{ |
212 | ····························string relname = rel.Name; |
213 | ····························if (relname[0]=='<') |
214 | ····························{ |
215 | ································int q = relname.IndexOf( '>' ); |
216 | ································if (q == -1) |
217 | ····································q = relname.Length; |
218 | ································relname = relname.Substring( 1, q - 1 ); |
219 | ····························} |
220 | ····························rel.RelationName = relname; |
221 | ························} |
222 | ························countWithoutName++; |
223 | ····················} |
224 | ················} |
225 | ············} |
226 | ········} |
227 | |
228 | |
229 | |
230 | |
231 | ········private string GetTypeFullName(Type t) |
232 | ········{ |
233 | ············NDOAssemblyName ndoAssName = new NDOAssemblyName(t.Assembly.FullName); |
234 | ············string type = t.FullName.Replace("+", "/"); |
235 | ············return "[" + ndoAssName.Name + "]" + type; |
236 | ········} |
237 | |
238 | ········public Class Class |
239 | ········{ |
240 | ············get |
241 | ············{ |
242 | ················// Mapping information isn't available to construction time. |
243 | ················// So we have to search the class information on demand. |
244 | ················if (myClass == null) |
245 | ················{ |
246 | ····················myClass = mappings.FindClass(this.classType.FullName); |
247 | ····················if (myClass == null) |
248 | ························throw new Exception("Can't find class mapping for class " + this.Name); |
249 | ················} |
250 | ················return myClass; |
251 | ············} |
252 | ········} |
253 | |
254 | ········public IList Relations |
255 | ········{ |
256 | ············get |
257 | ············{ |
258 | ················return this.relations; |
259 | ············} |
260 | ········} |
261 | |
262 | ········public IList Fields |
263 | ········{ |
264 | ············get |
265 | ············{ |
266 | ················return this.fields; |
267 | ············} |
268 | ········} |
269 | |
270 | ········public IList EmbeddedTypes |
271 | ········{ |
272 | ············get |
273 | ············{ |
274 | ················return this.embeddedTypes; |
275 | ············} |
276 | ········} |
277 | |
278 | ········public string Name |
279 | ········{ |
280 | ············get |
281 | ············{ |
282 | |
283 | ················return this.classType.FullName; |
284 | ············} |
285 | ········} |
286 | |
287 | ········public string GetILName(string assemblyName) |
288 | ········{ |
289 | ············return new ReflectedType(this.classType, assemblyName).ILName; |
290 | ········} |
291 | |
292 | ········public Type ClassType |
293 | ········{ |
294 | ············get { return this.classType; } |
295 | ········} |
296 | |
297 | |
298 | ········OidColumnAttribute[] columnAttributes; |
299 | ········public OidColumnAttribute[] ColumnAttributes |
300 | ········{ |
301 | ············get { return columnAttributes; } |
302 | ········} |
303 | |
304 | |
305 | ········public string BaseName |
306 | ········{ |
307 | ············get |
308 | ············{ |
309 | ················Type t = this.classType.BaseType; |
310 | ················if (t.IsGenericType) |
311 | ····················t = t.GetGenericTypeDefinition(); |
312 | ················return t.FullName; |
313 | ············} |
314 | ········} |
315 | |
316 | ········string baseFullName; |
317 | ········// As long as we don't need this, we leave it in the comment |
318 | ········//public string BaseFullName |
319 | ········//{ |
320 | ········//····get |
321 | ········//····{ |
322 | ········//········return this.baseFullName; |
323 | ········//····} |
324 | ········//} |
325 | |
326 | ········public string AssemblyName |
327 | ········{ |
328 | ············get |
329 | ············{ |
330 | ················NDOAssemblyName an = new NDOAssemblyName(this.classType.Assembly.FullName); |
331 | ················return an.Name; |
332 | ············} |
333 | ········} |
334 | |
335 | ········public override bool Equals(object obj) |
336 | ········{ |
337 | ············if (! (obj is ClassNode)) |
338 | ················return false; |
339 | ············return ((ClassNode) obj).Name == this.Name; |
340 | ········} |
341 | |
342 | ········public override int GetHashCode() |
343 | ········{ |
344 | ············// Fits to the definition of Equals |
345 | ············return this.Name.GetHashCode(); |
346 | ········} |
347 | |
348 | |
349 | ········public bool IsAbstractOrInterface |
350 | ········{ |
351 | ············get |
352 | ············{ |
353 | ················return isAbstract | isInterface; |
354 | ············} |
355 | ········} |
356 | ········ |
357 | ········bool isAbstract; |
358 | ········public bool IsAbstract |
359 | ········{ |
360 | ············get |
361 | ············{ |
362 | ················return isAbstract; |
363 | ············} |
364 | ········} |
365 | ········bool isInterface; |
366 | ········public bool IsInterface |
367 | ········{ |
368 | ············get |
369 | ············{ |
370 | ················return isInterface; |
371 | ············} |
372 | ········} |
373 | |
374 | ········bool isPoly; |
375 | ········public bool IsPoly |
376 | ········{ |
377 | ············get { return isPoly; } |
378 | ············set { isPoly = value; } |
379 | ········} |
380 | |
381 | ········bool isPersistent; |
382 | ········public bool IsPersistent |
383 | ········{ |
384 | ············// If A inherits from B inherits from C and |
385 | ············// A and C are [NDOPersistent] and B is not [NDOPersistent] |
386 | ············// then B is in the nodelist and has the attribute IsPersistent with |
387 | ············// the value "false". |
388 | ············get { return isPersistent; } |
389 | ········} |
390 | |
391 | ········public override string ToString() |
392 | ········{ |
393 | ············return this.name; |
394 | ········} |
395 | |
396 | ····} |
397 | } |
398 |
New Commit (15fdc4b)
1 | // |
2 | // Copyright (c) 2002-2016 Mirko Matytschak |
3 | // (www.netdataobjects.de) |
4 | // |
5 | // Author: Mirko Matytschak |
6 | // |
7 | // Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated |
8 | // documentation files (the "Software"), to deal in the Software without restriction, including without limitation |
9 | // the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the |
10 | // Software, and to permit persons to whom the Software is furnished to do so, subject to the following |
11 | // conditions: |
12 | |
13 | // The above copyright notice and this permission notice shall be included in all copies or substantial portions |
14 | // of the Software. |
15 | // |
16 | // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED |
17 | // TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL |
18 | // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF |
19 | // CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER |
20 | // DEALINGS IN THE SOFTWARE. |
21 | |
22 | |
23 | using System; |
24 | using System.Diagnostics; |
25 | using System.Reflection; |
26 | using System.Collections; |
27 | using System.Collections.Generic; |
28 | using System.Linq; |
29 | using NDO; |
30 | using NDO.Mapping; |
31 | using NDO.Mapping.Attributes; |
32 | |
33 | namespace NDOEnhancer |
34 | { |
35 | ····/// <summary> |
36 | ····/// Zusammenfassung für ClassNode. |
37 | ····/// </summary> |
38 | ····internal class ClassNode |
39 | ····{ |
40 | ········string name = null; |
41 | ········List<FieldNode> fields = new List<FieldNode>(); |
42 | ········List<RelationNode> relations = new List<RelationNode>(); |
43 | ········List<EmbeddedTypeNode> embeddedTypes = new List<EmbeddedTypeNode>(); |
44 | ········Class myClass = null; |
45 | ········Type classType; |
46 | ········NDOMapping mappings; |
47 | |
48 | ········public ClassNode(Type t, NDOMapping mappings) |
49 | ········{ |
50 | ············this.classType = t; |
51 | ············if (t.IsGenericType && !t.IsGenericTypeDefinition) |
52 | ················throw new InternalException(45, "ClassNode"); |
53 | ············this.mappings = mappings; |
54 | ············this.name = new ReflectedType(t).ILNameWithoutPrefix; |
55 | ············this.isInterface = t.IsInterface; |
56 | ············this.isPersistent = IsPersistentType(t); |
57 | |
58 | ············Type basetype = t.BaseType; |
59 | ············this.baseFullName = new ReflectedType(basetype).ILNameWithoutPrefix; |
60 | ············this.isAbstract = t.IsAbstract; |
61 | ············AnalyzeFields(); |
62 | ············CheckOidAttributes(); |
63 | ········} |
64 | |
65 | ········private bool IsPersistentType(Type t) |
66 | ········{ |
67 | ············return t.GetCustomAttributes(typeof(NDOPersistentAttribute), false).Length > 0; |
68 | ········} |
69 | |
70 | ········private void CheckOidAttributes() |
71 | ········{ |
72 | ············List<OidColumnAttribute> collectedAttributes = new List<OidColumnAttribute>(); |
73 | |
74 | ············object[] attributes = this.classType.GetCustomAttributes(typeof(OidColumnAttribute), true); |
75 | ············if (attributes.Length > 0) |
76 | ············{ |
77 | ················if (this.classType.GetCustomAttributes(typeof(NDOOidTypeAttribute), true).Length > 0) |
78 | ····················new MessageAdapter().WriteLine("Warning: Can't mix OidColumnAttribute and NDOOidTypeAttribute in type " + this.name + ". The NDOOidTypeAttribute is ignored."); |
79 | ················foreach (OidColumnAttribute ca in attributes) |
80 | ····················collectedAttributes.Add(ca); |
81 | ············} |
82 | ············else // Try to implement the old mapping |
83 | ············{ |
84 | ················// The attribute is collected from the first base class defining it |
85 | ················attributes = this.classType.GetCustomAttributes(typeof(NDOOidTypeAttribute), true); |
86 | ················if (attributes.Length > 0) |
87 | ····················collectedAttributes.Add(new OidColumnAttribute(((NDOOidTypeAttribute)attributes[0]).OidType)); |
88 | ············} |
89 | |
90 | ············FieldMap fieldMap = new FieldMap(this.classType); |
91 | ············foreach (var de in fieldMap.PersistentFields) |
92 | ············{ |
93 | ················FieldInfo fi = de.Value as FieldInfo; |
94 | ················if (fi == null) |
95 | ····················continue; |
96 | #pragma warning disable 0618 |
97 | ················if (fi.GetCustomAttributes(typeof(NDOObjectIdAttribute), false).Length > 0) |
98 | ················{ |
99 | ····················OidColumnAttribute ca = new OidColumnAttribute(); |
100 | ····················ca.FieldName = fi.Name; |
101 | ····················collectedAttributes.Add(ca); |
102 | ················} |
103 | #pragma warning restore 0618 |
104 | ············} |
105 | |
106 | ············// If no attribute is assigned to the class, look for attributes assigned to the assembly |
107 | ············if (collectedAttributes.Count == 0) |
108 | ············{ |
109 | ················attributes = this.classType.Assembly.GetCustomAttributes(typeof(OidColumnAttribute), false); |
110 | ················foreach (OidColumnAttribute ca in attributes) |
111 | ················{ |
112 | ····················ca.IsAssemblyWideDefinition = true; |
113 | ····················collectedAttributes.Add( ca ); |
114 | ················} |
115 | ············} |
116 | ············if (collectedAttributes.Count == 0) |
117 | ············{ |
118 | ················attributes = this.classType.Assembly.GetCustomAttributes(typeof(NDOOidTypeAttribute), false); |
119 | ················// The old mapping only allowed 1 NDOOidAttribute, so let's take the first one found |
120 | ················if (attributes.Length > 0) |
121 | ····················collectedAttributes.Add( new OidColumnAttribute( ((NDOOidTypeAttribute)attributes[0]).OidType ) { IsAssemblyWideDefinition = true } ); |
122 | ············} |
123 | ············if (collectedAttributes.Count > 0) |
124 | ············{ |
125 | ················this.columnAttributes = new OidColumnAttribute[collectedAttributes.Count]; |
126 | ················collectedAttributes.CopyTo(this.columnAttributes, 0); |
127 | ············} |
128 | ········} |
129 | |
130 | ········private void AnalyzeFields() |
131 | ········{ |
132 | ············IList relations = new ArrayList(); |
133 | ············var fis = this.classType.GetFields(BindingFlags.NonPublic | BindingFlags.Instance).Where(fi=>!fi.IsInitOnly); |
134 | ············foreach (FieldInfo fi in fis) |
135 | ············{ |
136 | ················string fname = fi.Name; |
137 | ················if (fname.StartsWith("_ndo")) |
138 | ····················continue; |
139 | |
140 | ················object[] attributes = fi.GetCustomAttributes(false); |
141 | ················bool cont = false; |
142 | ················foreach (System.Attribute attr in attributes) |
143 | ················{ |
144 | ····················if (attr is NDOTransientAttribute) |
145 | ····················{ |
146 | ························cont = true; |
147 | ························break; |
148 | ····················} |
149 | ····················if (attr is NDORelationAttribute) |
150 | ····················{ |
151 | ························this.relations.Add(new RelationNode(fi, (NDORelationAttribute)attr, this)); |
152 | ························cont = true; |
153 | ························break; |
154 | ····················} |
155 | ················} |
156 | ················if (cont) continue; |
157 | |
158 | ················if (fi.FieldType.IsSubclassOf( typeof( System.Delegate ) )) |
159 | ····················continue; |
160 | |
161 | ················// Field type is persistent - assume relation with element multiplicity. |
162 | ················if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType)) |
163 | ················{ |
164 | ····················NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType, RelationInfo.Default); |
165 | ····················this.relations.Add(new RelationNode(fi, nra, this)); |
166 | ····················continue; |
167 | ················} |
168 | |
169 | ················// Field is a collection - assume that it is either a relation or a transient field. |
170 | ················if (GenericIListReflector.IsGenericIList(fi.FieldType)) |
171 | ················{ |
172 | ····················if (typeof(IPersistenceCapable).IsAssignableFrom(fi.FieldType.GetGenericArguments()[0])) |
173 | ····················{ |
174 | ························NDORelationAttribute nra = new NDORelationAttribute(fi.FieldType.GetGenericArguments()[0], RelationInfo.Default); |
175 | ························this.relations.Add(new RelationNode(fi, nra, this)); |
176 | ····················} |
177 | ····················else |
178 | ····················{ |
179 | ························Console.WriteLine("Warning: The field " + this.name + "." + fi.Name + " is a generic collection to a nonpersistent type. NDO assumes, that this field is transient."); |
180 | ····················} |
181 | ····················continue; |
182 | ················} |
183 | |
184 | ················if (!fi.FieldType.IsGenericParameter && fi.FieldType.IsClass && fi.FieldType != typeof(string) && fi.FieldType != typeof(byte[])) |
185 | ················{ |
186 | ····················this.embeddedTypes.Add(new EmbeddedTypeNode(fi)); |
187 | ················} |
188 | ················else |
189 | ················{ |
190 | ····················FieldNode fn = new FieldNode(fi); |
191 | ····················this.fields.Add(fn); |
192 | ····················Type ft = fi.FieldType; |
193 | ····················if (ft.IsValueType && !ft.IsEnum && !StorableTypes.Contains(ft)) |
194 | ····················{ |
195 | ························ValueTypes.Instance.Add(new ValueTypeNode(ft)); |
196 | ····················} |
197 | ················} |
198 | ············} |
199 | |
200 | ············// If there is more than one relation to the same target type |
201 | ············// without relation name, assign a relation name automatically |
202 | ············foreach(var group in this.relations.GroupBy( r => r.RelatedType )) |
203 | ············{ |
204 | ················if (group.Count() < 2) |
205 | ····················continue; |
206 | ················int countWithoutName = 0; |
207 | ················foreach (var rel in group) |
208 | ················{ |
209 | ····················if (string.IsNullOrEmpty( rel.RelationName )) |
210 | ····················{ |
211 | ························if (countWithoutName > 0) |
212 | ························{ |
213 | ····························string relname = rel.Name; |
214 | ····························if (relname[0]=='<') |
215 | ····························{ |
216 | ································int q = relname.IndexOf( '>' ); |
217 | ································if (q == -1) |
218 | ····································q = relname.Length; |
219 | ································relname = relname.Substring( 1, q - 1 ); |
220 | ····························} |
221 | ····························rel.RelationName = relname; |
222 | ························} |
223 | ························countWithoutName++; |
224 | ····················} |
225 | ················} |
226 | ············} |
227 | ········} |
228 | |
229 | |
230 | |
231 | |
232 | ········private string GetTypeFullName(Type t) |
233 | ········{ |
234 | ············NDOAssemblyName ndoAssName = new NDOAssemblyName(t.Assembly.FullName); |
235 | ············string type = t.FullName.Replace("+", "/"); |
236 | ············return "[" + ndoAssName.Name + "]" + type; |
237 | ········} |
238 | |
239 | ········public Class Class |
240 | ········{ |
241 | ············get |
242 | ············{ |
243 | ················// Mapping information isn't available to construction time. |
244 | ················// So we have to search the class information on demand. |
245 | ················if (myClass == null) |
246 | ················{ |
247 | ····················myClass = mappings.FindClass(this.classType.FullName); |
248 | ····················if (myClass == null) |
249 | ························throw new Exception("Can't find class mapping for class " + this.Name); |
250 | ················} |
251 | ················return myClass; |
252 | ············} |
253 | ········} |
254 | |
255 | ········public IList Relations |
256 | ········{ |
257 | ············get |
258 | ············{ |
259 | ················return this.relations; |
260 | ············} |
261 | ········} |
262 | |
263 | ········public IList Fields |
264 | ········{ |
265 | ············get |
266 | ············{ |
267 | ················return this.fields; |
268 | ············} |
269 | ········} |
270 | |
271 | ········public IList EmbeddedTypes |
272 | ········{ |
273 | ············get |
274 | ············{ |
275 | ················return this.embeddedTypes; |
276 | ············} |
277 | ········} |
278 | |
279 | ········public string Name |
280 | ········{ |
281 | ············get |
282 | ············{ |
283 | |
284 | ················return this.classType.FullName; |
285 | ············} |
286 | ········} |
287 | |
288 | ········public string GetILName(string assemblyName) |
289 | ········{ |
290 | ············return new ReflectedType(this.classType, assemblyName).ILName; |
291 | ········} |
292 | |
293 | ········public Type ClassType |
294 | ········{ |
295 | ············get { return this.classType; } |
296 | ········} |
297 | |
298 | |
299 | ········OidColumnAttribute[] columnAttributes; |
300 | ········public OidColumnAttribute[] ColumnAttributes |
301 | ········{ |
302 | ············get { return columnAttributes; } |
303 | ········} |
304 | |
305 | |
306 | ········public string BaseName |
307 | ········{ |
308 | ············get |
309 | ············{ |
310 | ················Type t = this.classType.BaseType; |
311 | ················if (t.IsGenericType) |
312 | ····················t = t.GetGenericTypeDefinition(); |
313 | ················return t.FullName; |
314 | ············} |
315 | ········} |
316 | |
317 | ········string baseFullName; |
318 | ········// As long as we don't need this, we leave it in the comment |
319 | ········//public string BaseFullName |
320 | ········//{ |
321 | ········//····get |
322 | ········//····{ |
323 | ········//········return this.baseFullName; |
324 | ········//····} |
325 | ········//} |
326 | |
327 | ········public string AssemblyName |
328 | ········{ |
329 | ············get |
330 | ············{ |
331 | ················NDOAssemblyName an = new NDOAssemblyName(this.classType.Assembly.FullName); |
332 | ················return an.Name; |
333 | ············} |
334 | ········} |
335 | |
336 | ········public override bool Equals(object obj) |
337 | ········{ |
338 | ············if (! (obj is ClassNode)) |
339 | ················return false; |
340 | ············return ((ClassNode) obj).Name == this.Name; |
341 | ········} |
342 | |
343 | ········public override int GetHashCode() |
344 | ········{ |
345 | ············// Fits to the definition of Equals |
346 | ············return this.Name.GetHashCode(); |
347 | ········} |
348 | |
349 | |
350 | ········public bool IsAbstractOrInterface |
351 | ········{ |
352 | ············get |
353 | ············{ |
354 | ················return isAbstract | isInterface; |
355 | ············} |
356 | ········} |
357 | ········ |
358 | ········bool isAbstract; |
359 | ········public bool IsAbstract |
360 | ········{ |
361 | ············get |
362 | ············{ |
363 | ················return isAbstract; |
364 | ············} |
365 | ········} |
366 | ········bool isInterface; |
367 | ········public bool IsInterface |
368 | ········{ |
369 | ············get |
370 | ············{ |
371 | ················return isInterface; |
372 | ············} |
373 | ········} |
374 | |
375 | ········bool isPoly; |
376 | ········public bool IsPoly |
377 | ········{ |
378 | ············get { return isPoly; } |
379 | ············set { isPoly = value; } |
380 | ········} |
381 | |
382 | ········bool isPersistent; |
383 | ········public bool IsPersistent |
384 | ········{ |
385 | ············// If A inherits from B inherits from C and |
386 | ············// A and C are [NDOPersistent] and B is not [NDOPersistent] |
387 | ············// then B is in the nodelist and has the attribute IsPersistent with |
388 | ············// the value "false". |
389 | ············get { return isPersistent; } |
390 | ········} |
391 | |
392 | ········public override string ToString() |
393 | ········{ |
394 | ············return this.name; |
395 | ········} |
396 | |
397 | ····} |
398 | } |
399 |