You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
Lidarr/Marr.Data/Mapping/FluentMappings.cs

234 lines
9.9 KiB

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