using System; using System.Reflection; using Marr.Data.Mapping.Strategies; using System.Collections; namespace Marr.Data.Mapping { /// /// Provides a fluent interface for mapping domain entities and properties to database tables and columns. /// public class FluentMappings { private bool _publicOnly; public FluentMappings() : this(true) { } public FluentMappings(bool publicOnly) { _publicOnly = publicOnly; } public MappingsFluentEntity Entity() { return new MappingsFluentEntity(_publicOnly); } public class MappingsFluentEntity { public MappingsFluentEntity(bool publicOnly) { Columns = new MappingsFluentColumns(this, publicOnly); Table = new MappingsFluentTables(this); Relationships = new MappingsFluentRelationships(this, publicOnly); } /// /// Contains methods that map entity properties to database table and view column names; /// public MappingsFluentColumns Columns { get; private set; } /// /// Contains methods that map entity classes to database table names. /// public MappingsFluentTables Table { get; private set; } /// /// Contains methods that map sub-entities with database table and view column names. /// public MappingsFluentRelationships Relationships { get; private set; } } public class MappingsFluentColumns { private bool _publicOnly; private MappingsFluentEntity _fluentEntity; public MappingsFluentColumns(MappingsFluentEntity fluentEntity, bool publicOnly) { _fluentEntity = fluentEntity; _publicOnly = publicOnly; } /// /// Creates column mappings for the given type. /// Maps all properties except ICollection properties. /// /// The type that is being built. /// public ColumnMapBuilder AutoMapAllProperties() { return AutoMapPropertiesWhere(m => m.MemberType == MemberTypes.Property && !typeof(ICollection).IsAssignableFrom((m as PropertyInfo).PropertyType)); } /// /// Creates column mappings for the given type. /// Maps all properties that are simple types (int, string, DateTime, etc). /// ICollection properties are not included. /// /// The type that is being built. /// public ColumnMapBuilder AutoMapSimpleTypeProperties() { return AutoMapPropertiesWhere(m => m.MemberType == MemberTypes.Property && DataHelper.IsSimpleType((m as PropertyInfo).PropertyType) && !typeof(ICollection).IsAssignableFrom((m as PropertyInfo).PropertyType)); } /// /// Creates column mappings for the given type if they match the predicate. /// /// The type that is being built. /// Determines whether a mapping should be created based on the member info. /// public ColumnMapBuilder AutoMapPropertiesWhere(Func predicate) { Type entityType = typeof(TEntity); ConventionMapStrategy strategy = new ConventionMapStrategy(_publicOnly); strategy.ColumnPredicate = predicate; ColumnMapCollection columns = strategy.MapColumns(entityType); MapRepository.Instance.Columns[entityType] = columns; return new ColumnMapBuilder(_fluentEntity, columns); } /// /// Creates a ColumnMapBuilder that starts out with no pre-populated columns. /// All columns must be added manually using the builder. /// /// /// public ColumnMapBuilder MapProperties() { Type entityType = typeof(TEntity); ColumnMapCollection columns = new ColumnMapCollection(); MapRepository.Instance.Columns[entityType] = columns; return new ColumnMapBuilder(_fluentEntity, columns); } } public class MappingsFluentTables { private MappingsFluentEntity _fluentEntity; public MappingsFluentTables(MappingsFluentEntity fluentEntity) { _fluentEntity = fluentEntity; } /// /// Provides a fluent table mapping interface. /// /// /// public TableBuilder AutoMapTable() { return new TableBuilder(_fluentEntity); } /// /// Sets the table name for a given type. /// /// /// public TableBuilder MapTable(string tableName) { return new TableBuilder(_fluentEntity).SetTableName(tableName); } } public class MappingsFluentRelationships { private MappingsFluentEntity _fluentEntity; private bool _publicOnly; public MappingsFluentRelationships(MappingsFluentEntity fluentEntity, bool publicOnly) { _fluentEntity = fluentEntity; _publicOnly = publicOnly; } /// /// Creates relationship mappings for the given type. /// Maps all properties that implement ICollection or are not "simple types". /// /// public RelationshipBuilder AutoMapICollectionOrComplexProperties() { return AutoMapPropertiesWhere(m => m.MemberType == MemberTypes.Property && ( typeof(ICollection).IsAssignableFrom((m as PropertyInfo).PropertyType) || !DataHelper.IsSimpleType((m as PropertyInfo).PropertyType) ) ); } /// /// Creates relationship mappings for the given type. /// Maps all properties that implement ICollection. /// /// public RelationshipBuilder AutoMapICollectionProperties() { return AutoMapPropertiesWhere(m => m.MemberType == MemberTypes.Property && typeof(ICollection).IsAssignableFrom((m as PropertyInfo).PropertyType)); } /// /// Creates relationship mappings for the given type. /// Maps all properties that are not "simple types". /// /// public RelationshipBuilder AutoMapComplexTypeProperties() { return AutoMapPropertiesWhere(m => m.MemberType == MemberTypes.Property && !DataHelper.IsSimpleType((m as PropertyInfo).PropertyType) && !MapRepository.Instance.TypeConverters.ContainsKey((m as PropertyInfo).PropertyType)); } /// /// Creates relationship mappings for the given type if they match the predicate. /// /// Determines whether a mapping should be created based on the member info. /// public RelationshipBuilder AutoMapPropertiesWhere(Func predicate) { Type entityType = typeof(TEntity); ConventionMapStrategy strategy = new ConventionMapStrategy(_publicOnly); strategy.RelationshipPredicate = predicate; RelationshipCollection relationships = strategy.MapRelationships(entityType); MapRepository.Instance.Relationships[entityType] = relationships; return new RelationshipBuilder(_fluentEntity, relationships); } /// /// Creates a RelationshipBuilder that starts out with no pre-populated relationships. /// All relationships must be added manually using the builder. /// /// public RelationshipBuilder MapProperties() { Type entityType = typeof(T); RelationshipCollection relationships = new RelationshipCollection(); MapRepository.Instance.Relationships[entityType] = relationships; return new RelationshipBuilder(_fluentEntity, relationships); } } } }