1 #region MIT license
2 //
3 // MIT license
4 //
5 // Copyright (c) 2007-2008 Jiri Moudry, Stefan Klinger
6 //
7 // Permission is hereby granted, free of charge, to any person obtaining a copy
8 // of this software and associated documentation files (the "Software"), to deal
9 // in the Software without restriction, including without limitation the rights
10 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
11 // copies of the Software, and to permit persons to whom the Software is
12 // furnished to do so, subject to the following conditions:
13 //
14 // The above copyright notice and this permission notice shall be included in
15 // all copies or substantial portions of the Software.
16 //
17 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
18 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
19 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
20 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
21 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
22 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
23 // THE SOFTWARE.
24 //
25 #endregion
26 
27 using System;
28 using System.Collections.ObjectModel;
29 using System.Data.Linq.Mapping;
30 using System.Diagnostics;
31 using System.Linq;
32 using System.Reflection;
33 using DbLinq.Util;
34 using System.Collections.Generic;
35 
36 namespace DbLinq.Data.Linq.Mapping
37 {
38     [DebuggerDisplay("MetaType for {Name}")]
39     internal class AttributedMetaType : MetaType
40     {
AttributedMetaType(Type classType)41         internal AttributedMetaType(Type classType)
42         {
43             type = classType;
44 
45 			AssociationsLookup = new Dictionary<MemberInfo, MetaDataMember>();
46 			_AssociationFixupList = new List<AssociationData>();
47 
48 			//First add the member to the AssociationsLookup table, because creation of the Association will cause both meta classes to look each other up, or possibly a self lookup
49 			//We'll also cache the association data in _AssociationFixupList to be used by GetAssociations
50 			foreach (var memberInfo in type.GetMembers())
51 			{
52 				var association = memberInfo.GetAttribute<AssociationAttribute>();
53 				if (association == null)
54 					continue;
55 				var dataMember = new AttributedAssociationMetaDataMember(memberInfo, association, this);
56 				AssociationsLookup[memberInfo] = dataMember;
57 				_AssociationFixupList.Add(new AssociationData() { Association = association, Member = memberInfo, DataMember = dataMember });
58 			}
59         }
60 
SetMetaTable(MetaTable metaTable)61         internal void SetMetaTable(MetaTable metaTable)
62         {
63             table = metaTable;
64         }
65 
66         private ReadOnlyCollection<MetaAssociation> _associations;
67         public override ReadOnlyCollection<MetaAssociation> Associations
68         {
69             get {
70                 if (_associations == null)
71                 {
72                     _associations = GetAssociations().ToList().AsReadOnly();
73                 }
74                 return _associations;
75             }
76         }
77 
78 		private class AssociationData
79 		{
80 			public AssociationAttribute Association;
81 			public MemberInfo Member;
82 			public AttributedAssociationMetaDataMember DataMember;
83 		}
84 
GetAssociations()85         private IEnumerable<MetaAssociation> GetAssociations()
86         {
87 			//We can clear our fixup list as we're now going to convert it to the association list
88 			var associationFixupList = _AssociationFixupList;
89 			_AssociationFixupList = null;
90 
91 			foreach (AssociationData data in associationFixupList)
92 			{
93 				var metaAssociation = new AttributedMetaAssociation(data.Member, data.Association, data.DataMember);
94 				data.DataMember.SetAssociation(metaAssociation);
95                 yield return metaAssociation;
96 			}
97         }
98 
99         public override bool CanInstantiate
100         {
101             // TODO: shall we expect something else?
102             get { return true; }
103         }
104 
105         private ReadOnlyCollection<MetaDataMember> dataMembers;
106         public override ReadOnlyCollection<MetaDataMember> DataMembers
107         {
108             get {
109                 if (dataMembers == null)
110                 {
111                     dataMembers =
112                         (from m in type.GetMembers()
113                          let c = m.GetAttribute<ColumnAttribute>()
114                          where c != null
115                          select (MetaDataMember) new AttributedColumnMetaDataMember(m, c, this))
116                         .ToList().AsReadOnly();
117                 }
118                 return dataMembers;
119             }
120         }
121 
122         public override MetaDataMember DBGeneratedIdentityMember
123         {
124             get { throw new NotImplementedException(); }
125         }
126 
127         public override ReadOnlyCollection<MetaType> DerivedTypes
128         {
129             get { throw new NotImplementedException(); }
130         }
131 
132         public override MetaDataMember Discriminator
133         {
134             get { throw new NotImplementedException(); }
135         }
136 
GetDataMember(MemberInfo member)137         public override MetaDataMember GetDataMember(MemberInfo member)
138         {
139             // TODO: optimize?
140             // A tip to know the MemberInfo for the same member is not the same when declared from a class and its inheritor
141             return (from m in PersistentDataMembers where m.Member.Name == member.Name select m).SingleOrDefault();
142         }
143 
GetInheritanceType(Type baseType)144         public override MetaType GetInheritanceType(Type baseType)
145         {
146             throw new NotImplementedException();
147         }
148 
GetTypeForInheritanceCode(object code)149         public override MetaType GetTypeForInheritanceCode(object code)
150         {
151             throw new NotImplementedException();
152         }
153 
154         public override bool HasAnyLoadMethod
155         {
156             get { throw new NotImplementedException(); }
157         }
158 
159         public override bool HasAnyValidateMethod
160         {
161             get { throw new NotImplementedException(); }
162         }
163 
164         public override bool HasInheritance
165         {
166             get { throw new NotImplementedException(); }
167         }
168 
169         public override bool HasInheritanceCode
170         {
171             get { throw new NotImplementedException(); }
172         }
173 
174         public override bool HasUpdateCheck
175         {
176             get { throw new NotImplementedException(); }
177         }
178 
179         private ReadOnlyCollection<MetaDataMember> identityMembers;
180         public override ReadOnlyCollection<MetaDataMember> IdentityMembers
181         {
182             get {
183                 if (identityMembers == null)
184                     identityMembers =
185                         DataMembers.Where(m => m.IsPrimaryKey).ToList().AsReadOnly();
186                 return identityMembers;
187             }
188         }
189 
190         public override MetaType InheritanceBase
191         {
192             get { throw new NotImplementedException(); }
193         }
194 
195         public override object InheritanceCode
196         {
197             get { throw new NotImplementedException(); }
198         }
199 
200         public override MetaType InheritanceDefault
201         {
202             get { throw new NotImplementedException(); }
203         }
204 
205         public override MetaType InheritanceRoot
206         {
207             get { throw new NotImplementedException(); }
208         }
209 
210         public override ReadOnlyCollection<MetaType> InheritanceTypes
211         {
212             get { throw new NotImplementedException(); }
213         }
214 
215         public override bool IsEntity
216         {
217             get { return true; }
218         }
219 
220         public override bool IsInheritanceDefault
221         {
222             get { throw new NotImplementedException(); }
223         }
224 
225         public override MetaModel Model
226         {
227             get { return Table.Model; }
228         }
229 
230         public override string Name
231         {
232             get { return type.Name; }
233         }
234 
235         public override MethodInfo OnLoadedMethod
236         {
237             get { throw new NotImplementedException(); }
238         }
239 
240         public override MethodInfo OnValidateMethod
241         {
242             get { throw new NotImplementedException(); }
243         }
244 
245     	private ReadOnlyCollection<MetaDataMember> _persistentDataMembers;
246         public override ReadOnlyCollection<MetaDataMember> PersistentDataMembers
247         {
248             get {
249                 if (_persistentDataMembers == null)
250                     _persistentDataMembers =
251                         DataMembers.Where(m => m.IsPersistent).ToList().AsReadOnly();
252                 return _persistentDataMembers;
253             }
254         }
255 
256         private MetaTable table;
257         public override MetaTable Table
258         {
259             get { return table; }
260         }
261 
262         private readonly Type type;
263         public override Type Type
264         {
265             get { return type; }
266         }
267 
268         public override MetaDataMember VersionMember
269         {
270             get { throw new NotImplementedException(); }
271         }
272 
273 		internal Dictionary<MemberInfo, MetaDataMember> AssociationsLookup;
274 		private List<AssociationData> _AssociationFixupList;
275     }
276 }
277