PageRenderTime 54ms CodeModel.GetById 21ms RepoModel.GetById 0ms app.codeStats 0ms

/Source/facebook.Linq/Linq/Metamodel.cs

https://bitbucket.org/assaframan/facebooklinq
C# | 176 lines | 145 code | 22 blank | 9 comment | 29 complexity | 45d8151eb550a7e1eedfac1981cbd61e MD5 | raw file
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using System.Web;
  5. using System.Reflection;
  6. using System.Data.Linq.Mapping;
  7. using Microsoft.Xml.Schema.Linq;
  8. namespace facebook.Linq
  9. {
  10. /// <summary>
  11. /// Property metadata descriptor
  12. /// </summary>
  13. public class PropertyData
  14. {
  15. internal PropertyData()
  16. {
  17. }
  18. internal PropertyData(PropertyInfo pi)
  19. {
  20. this.PropertyInfo = pi;
  21. ColumnAttribute = ReflectionHelper.GetAttributes<ColumnAttribute>(pi, true).FirstOrDefault();
  22. FqlFieldName = GetLinqFieldName();
  23. IsLinqIdentity = GetIsLinqIdentity();
  24. }
  25. ColumnAttribute ColumnAttribute;
  26. internal PropertyInfo PropertyInfo;
  27. internal string FqlFieldName;
  28. internal bool IsLinqIdentity;
  29. internal bool GetIsLinqIdentity()
  30. {
  31. if (ColumnAttribute != null)
  32. return ColumnAttribute.IsPrimaryKey;
  33. return false; //TODO:
  34. }
  35. internal string GetLinqFieldName()
  36. {
  37. if (ColumnAttribute != null)
  38. return ColumnAttribute.Name;
  39. return PropertyInfo.Name.ToFqlIdentifier();
  40. }
  41. }
  42. /// <summary>
  43. /// Type metadata descriptor cache
  44. /// </summary>
  45. internal class KnownTypeData
  46. {
  47. static object GetTypeDataEntrance = new object();
  48. internal static TypeData GetTypeData(Type t)
  49. {
  50. if (Types.ContainsKey(t))
  51. return Types[t];
  52. lock (GetTypeDataEntrance)
  53. {
  54. if (Types.ContainsKey(t))
  55. return Types[t];
  56. var td = new TypeData(t);
  57. Types.Add(t, td);
  58. if(td.FqlTableName!=null)
  59. TypesByTableName.Add(td.FqlTableName, td);
  60. return td;
  61. }
  62. }
  63. internal static TypeData GetTypeDataByTableName(string tableName)
  64. {
  65. return TypesByTableName.TryGetValue(tableName);
  66. }
  67. static Dictionary<string, TypeData> TypesByTableName = new Dictionary<string, TypeData>();
  68. static Dictionary<Type, TypeData> Types = new Dictionary<Type, TypeData>();
  69. }
  70. /// <summary>
  71. /// Type metadata descriptor
  72. /// </summary>
  73. internal class TypeData
  74. {
  75. internal TypeData()
  76. {
  77. }
  78. internal TypeData(Type t)
  79. {
  80. this.Type = t;
  81. FqlTableName = t.GetLinqTableName();
  82. if (FqlTableName != null)
  83. {
  84. foreach (var p in t.GetProperties())
  85. {
  86. if (p.IsFqlColumn())
  87. {
  88. var pd = new PropertyData(p);
  89. Properties.Add(p.Name, pd);
  90. PropertiesByFieldName.Add(pd.FqlFieldName, pd);
  91. if (pd.IsLinqIdentity)
  92. {
  93. if (IdentityProperty == null)
  94. IdentityProperty = pd;
  95. else
  96. throw new Exception("Type " + t.FullName + " has more than one identity property specified");
  97. }
  98. }
  99. }
  100. }
  101. }
  102. internal Type Type;
  103. internal string FqlTableName;
  104. internal Dictionary<string, PropertyData> Properties = new Dictionary<string, PropertyData>();
  105. internal Dictionary<string, PropertyData> PropertiesByFieldName = new Dictionary<string, PropertyData>();
  106. internal PropertyData GetPropertyByFieldName(string propertyName)
  107. {
  108. if (PropertiesByFieldName.ContainsKey(propertyName))
  109. return PropertiesByFieldName[propertyName];
  110. return null;
  111. }
  112. internal PropertyData IdentityProperty;
  113. }
  114. internal static class Helper
  115. {
  116. internal static bool IsFqlColumn(this PropertyInfo pi)
  117. {
  118. if (pi.DeclaringType.IsSubclassOf(typeof(XTypedElement)) && pi.GetSetMethod()!=null && IsSupported(pi.PropertyType))
  119. return true;
  120. return pi.GetCustomAttributes(typeof(ColumnAttribute), true).Length > 0;
  121. }
  122. static HashSet<Type> SupportedTypes = new HashSet<Type> { typeof(Int64), typeof(Decimal), typeof(string), typeof(bool), typeof(DateTime) };
  123. private static bool IsSupported(Type type)
  124. {
  125. if (type.IsEnum)
  126. return true;
  127. if (SupportedTypes.Contains(type))
  128. return true;
  129. var uType = Nullable.GetUnderlyingType(type);
  130. if (uType!=null && uType != type)
  131. return IsSupported(uType);
  132. return false;
  133. }
  134. internal static string ToFqlIdentifier(this string s)
  135. {
  136. return StringHelper.SplitByCaps(s).StringConcat("").ToLower();
  137. }
  138. internal static string GetLinqTableName(this Type type)
  139. {
  140. if (type.IsSubclassOf(typeof(XTypedElement)))
  141. {
  142. if (type.Name == "facebookevent")
  143. return "event";
  144. else if (type.Name == "friend_info")
  145. return "friend";
  146. return type.Name;
  147. }
  148. var t = type.GetCustomAttributes(typeof(TableAttribute), true);
  149. if (t.Length > 0)
  150. return (t[0] as TableAttribute).Name;
  151. return null;
  152. }
  153. }
  154. }