/* Copyright (C) 2008 - 2011 Jordan Marr This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This library is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General Public License along with this library. If not, see . */ using System; using System.Collections.Generic; using Marr.Data.Converters; using Marr.Data.Parameters; using Marr.Data.Mapping; using Marr.Data.Mapping.Strategies; using Marr.Data.Reflection; namespace Marr.Data { public class MapRepository { private static readonly object _tablesLock = new object(); private static readonly object _columnsLock = new object(); private static readonly object _relationshipsLock = new object(); private IDbTypeBuilder _dbTypeBuilder; private Dictionary _columnMapStrategies; internal Dictionary Tables { get; set; } internal Dictionary Columns { get; set; } internal Dictionary Relationships { get; set; } public Dictionary TypeConverters { get; private set; } // Explicit static constructor to tell C# compiler // not to mark type as beforefieldinit static MapRepository() { } private MapRepository() { Tables = new Dictionary(); Columns = new Dictionary(); Relationships = new Dictionary(); TypeConverters = new Dictionary(); // Register a default IReflectionStrategy ReflectionStrategy = new SimpleReflectionStrategy(); // Register a default type converter for Enums TypeConverters.Add(typeof(Enum), new EnumStringConverter()); // Register a default IDbTypeBuilder _dbTypeBuilder = new DbTypeBuilder(); _columnMapStrategies = new Dictionary(); RegisterDefaultMapStrategy(new AttributeMapStrategy()); EnableTraceLogging = false; } private readonly static MapRepository _instance = new MapRepository(); /// /// Gets a reference to the singleton MapRepository. /// public static MapRepository Instance { get { return _instance; } } /// /// Gets or sets a boolean that determines whether debug information should be written to the trace log. /// The default is false. /// public bool EnableTraceLogging { get; set; } #region - Column Map Strategies - public void RegisterDefaultMapStrategy(IMapStrategy strategy) { RegisterMapStrategy(typeof(object), strategy); } public void RegisterMapStrategy(Type entityType, IMapStrategy strategy) { if (_columnMapStrategies.ContainsKey(entityType)) _columnMapStrategies[entityType] = strategy; else _columnMapStrategies.Add(entityType, strategy); } private IMapStrategy GetMapStrategy(Type entityType) { if (_columnMapStrategies.ContainsKey(entityType)) { // Return entity specific column map strategy return _columnMapStrategies[entityType]; } // Return the default column map strategy return _columnMapStrategies[typeof(object)]; } #endregion #region - Table repository - internal string GetTableName(Type entityType) { if (!Tables.ContainsKey(entityType)) { lock (_tablesLock) { if (!Tables.ContainsKey(entityType)) { string tableName = GetMapStrategy(entityType).MapTable(entityType); Tables.Add(entityType, tableName); return tableName; } } } return Tables[entityType]; } #endregion #region - Columns repository - public ColumnMapCollection GetColumns(Type entityType) { if (!Columns.ContainsKey(entityType)) { lock (_columnsLock) { if (!Columns.ContainsKey(entityType)) { ColumnMapCollection columnMaps = GetMapStrategy(entityType).MapColumns(entityType); Columns.Add(entityType, columnMaps); return columnMaps; } } } return Columns[entityType]; } #endregion #region - Relationships repository - public RelationshipCollection GetRelationships(Type type) { if (!Relationships.ContainsKey(type)) { lock (_relationshipsLock) { if (!Relationships.ContainsKey(type)) { RelationshipCollection relationships = GetMapStrategy(type).MapRelationships(type); Relationships.Add(type, relationships); return relationships; } } } return Relationships[type]; } #endregion #region - Reflection Strategy - /// /// Gets or sets the reflection strategy that the DataMapper will use to load entities. /// By default the CachedReflector will be used, which provides a performance increase over the SimpleReflector. /// However, the SimpleReflector can be used in Medium Trust enviroments. /// /// public IReflectionStrategy ReflectionStrategy { get; set; } #endregion #region - Type Converters - /// /// Registers a converter for a given type. /// /// The CLR data type that will be converted. /// An IConverter object that will handle the data conversion. public void RegisterTypeConverter(Type type, IConverter converter) { TypeConverters[type] = converter; } /// /// Checks for a type converter (if one exists). /// 1) Checks for a converter registered for the current columns data type. /// 2) Checks to see if a converter is registered for all enums (type of Enum) if the current column is an enum. /// 3) Checks to see if a converter is registered for all objects (type of Object). /// /// The current data map. /// Returns an IConverter object or null if one does not exist. internal IConverter GetConverter(Type dataType) { if (TypeConverters.ContainsKey(dataType)) { // User registered type converter return TypeConverters[dataType]; } if (TypeConverters.ContainsKey(typeof(Enum)) && dataType.IsEnum) { // A converter is registered to handled enums return TypeConverters[typeof(Enum)]; } if (TypeConverters.ContainsKey(typeof(object))) { // User registered default converter return TypeConverters[typeof(object)]; } // No conversion return null; } #endregion #region - DbTypeBuilder - /// /// Gets or sets the IDBTypeBuilder that is responsible for converting parameter DbTypes based on the parameter value. /// Defaults to use the DbTypeBuilder. /// You can replace this with a more specific builder if you want more control over the way the parameter types are set. /// public IDbTypeBuilder DbTypeBuilder { get { return _dbTypeBuilder; } set { _dbTypeBuilder = value; } } #endregion } }