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