PageRenderTime 48ms CodeModel.GetById 22ms RepoModel.GetById 1ms app.codeStats 0ms

/src/FluentNHibernate/Mapping/CompositeElementPart.cs

http://github.com/jagregory/fluent-nhibernate
C# | 189 lines | 100 code | 29 blank | 60 comment | 3 complexity | 0a5d05c53c5497aacd97dd5599114dbf MD5 | raw file
Possible License(s): BSD-3-Clause, CC-BY-SA-3.0, Apache-2.0
  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq.Expressions;
  4. using System.Reflection;
  5. using FluentNHibernate.Mapping.Providers;
  6. using FluentNHibernate.MappingModel;
  7. using FluentNHibernate.MappingModel.Collections;
  8. using FluentNHibernate.Utils;
  9. namespace FluentNHibernate.Mapping
  10. {
  11. /// <summary>
  12. /// Component-element for component HasMany's.
  13. /// </summary>
  14. /// <typeparam name="T">Component type</typeparam>
  15. public class CompositeElementPart<T> : ICompositeElementMappingProvider, INestedCompositeElementMappingProvider
  16. {
  17. readonly Type entity;
  18. readonly Member member;
  19. readonly List<IPropertyMappingProvider> properties = new List<IPropertyMappingProvider>();
  20. readonly List<IManyToOneMappingProvider> references = new List<IManyToOneMappingProvider>();
  21. readonly List<INestedCompositeElementMappingProvider> components = new List<INestedCompositeElementMappingProvider>();
  22. readonly AttributeStore attributes = new AttributeStore();
  23. public CompositeElementPart(Type entity)
  24. {
  25. this.entity = entity;
  26. }
  27. public CompositeElementPart(Type entity, Member member)
  28. : this(entity)
  29. {
  30. this.member = member;
  31. }
  32. /// <summary>
  33. /// Map a property
  34. /// </summary>
  35. /// <param name="expression">Property</param>
  36. /// <example>
  37. /// Map(x => x.Age);
  38. /// </example>
  39. public PropertyPart Map(Expression<Func<T, object>> expression)
  40. {
  41. return Map(expression, null);
  42. }
  43. /// <summary>
  44. /// Map a property
  45. /// </summary>
  46. /// <param name="expression">Property</param>
  47. /// <param name="columnName">Column name</param>
  48. /// <example>
  49. /// Map(x => x.Age, "person_age");
  50. /// </example>
  51. public PropertyPart Map(Expression<Func<T, object>> expression, string columnName)
  52. {
  53. return Map(expression.ToMember(), columnName);
  54. }
  55. protected virtual PropertyPart Map(Member property, string columnName)
  56. {
  57. var propertyMap = new PropertyPart(property, typeof(T));
  58. if (!string.IsNullOrEmpty(columnName))
  59. propertyMap.Column(columnName);
  60. properties.Add(propertyMap);
  61. return propertyMap;
  62. }
  63. /// <summary>
  64. /// Create a reference to another entity. In database terms, this is a many-to-one
  65. /// relationship.
  66. /// </summary>
  67. /// <typeparam name="TOther">Other entity</typeparam>
  68. /// <param name="expression">Property on the current entity</param>
  69. /// <example>
  70. /// References(x => x.Company);
  71. /// </example>
  72. public ManyToOnePart<TOther> References<TOther>(Expression<Func<T, TOther>> expression)
  73. {
  74. return References(expression, null);
  75. }
  76. /// <summary>
  77. /// Create a reference to another entity. In database terms, this is a many-to-one
  78. /// relationship.
  79. /// </summary>
  80. /// <typeparam name="TOther">Other entity</typeparam>
  81. /// <param name="expression">Property on the current entity</param>
  82. /// <param name="columnName">Column name</param>
  83. /// <example>
  84. /// References(x => x.Company, "person_company_id");
  85. /// </example>
  86. public ManyToOnePart<TOther> References<TOther>(Expression<Func<T, TOther>> expression, string columnName)
  87. {
  88. return References<TOther>(expression.ToMember(), columnName);
  89. }
  90. protected virtual ManyToOnePart<TOther> References<TOther>(Member property, string columnName)
  91. {
  92. var part = new ManyToOnePart<TOther>(typeof(T), property);
  93. if (columnName != null)
  94. part.Column(columnName);
  95. references.Add(part);
  96. return part;
  97. }
  98. /// <summary>
  99. /// Maps a property of the component class as a reference back to the containing entity
  100. /// </summary>
  101. /// <param name="expression">Parent reference property</param>
  102. /// <returns>Component being mapped</returns>
  103. public void ParentReference(Expression<Func<T, object>> expression)
  104. {
  105. var parentMapping = new ParentMapping
  106. {
  107. ContainingEntityType = entity
  108. };
  109. parentMapping.Set(x => x.Name, Layer.Defaults, expression.ToMember().Name);
  110. attributes.Set("Parent", Layer.Defaults, parentMapping);
  111. }
  112. /// <summary>
  113. /// Create a nested component mapping.
  114. /// </summary>
  115. /// <param name="property">Component property</param>
  116. /// <param name="nestedCompositeElementAction">Action for creating the component</param>
  117. /// <example>
  118. /// HasMany(x => x.Locations)
  119. /// .Component(c =>
  120. /// {
  121. /// c.Map(x => x.Name);
  122. /// c.Component(x => x.Address, addr =>
  123. /// {
  124. /// addr.Map(x => x.Street);
  125. /// addr.Map(x => x.PostCode);
  126. /// });
  127. /// });
  128. /// </example>
  129. public void Component<TChild>(Expression<Func<T, TChild>> property, Action<CompositeElementPart<TChild>> nestedCompositeElementAction)
  130. {
  131. var nestedCompositeElement = new CompositeElementPart<TChild>(entity, property.ToMember());
  132. nestedCompositeElementAction(nestedCompositeElement);
  133. components.Add(nestedCompositeElement);
  134. }
  135. void PopulateMapping(CompositeElementMapping mapping)
  136. {
  137. mapping.ContainingEntityType = entity;
  138. mapping.Set(x => x.Class, Layer.Defaults, new TypeReference(typeof(T)));
  139. foreach (var property in properties)
  140. mapping.AddProperty(property.GetPropertyMapping());
  141. foreach (var reference in references)
  142. mapping.AddReference(reference.GetManyToOneMapping());
  143. foreach (var component in components)
  144. mapping.AddCompositeElement(component.GetCompositeElementMapping());
  145. }
  146. CompositeElementMapping ICompositeElementMappingProvider.GetCompositeElementMapping()
  147. {
  148. var mapping = new CompositeElementMapping(attributes.Clone());
  149. PopulateMapping(mapping);
  150. return mapping;
  151. }
  152. NestedCompositeElementMapping INestedCompositeElementMappingProvider.GetCompositeElementMapping()
  153. {
  154. var mapping = new NestedCompositeElementMapping(attributes.Clone());
  155. mapping.Set(x => x.Name, Layer.Defaults, member.Name);
  156. PopulateMapping(mapping);
  157. return mapping;
  158. }
  159. }
  160. }