using compiled delegate instead of reflection in Marr

This commit is contained in:
kay.one 2013-06-02 20:15:56 -07:00
commit ace98831c7
16 changed files with 170 additions and 388 deletions

View file

@ -14,11 +14,9 @@ You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.Collections.Generic;
using System.Text;
using System.Data;
using System.Reflection;
using Marr.Data.Converters;
using Marr.Data.Reflection;
namespace Marr.Data.Mapping
{
@ -27,6 +25,7 @@ namespace Marr.Data.Mapping
/// </summary>
public class ColumnMap
{
/// <summary>
/// Creates a column map with an empty ColumnInfo object.
/// </summary>
@ -38,32 +37,34 @@ namespace Marr.Data.Mapping
public ColumnMap(MemberInfo member, IColumnInfo columnInfo)
{
FieldName = member.Name;
ColumnInfo = columnInfo;
// If the column name is not specified, the field name will be used.
if (string.IsNullOrEmpty(columnInfo.Name))
columnInfo.Name = member.Name;
FieldType = ReflectionHelper.GetMemberType(member);
Type paramNetType = FieldType;
MapRepository repository = MapRepository.Instance;
IConverter converter = repository.GetConverter(FieldType);
if (converter != null)
Converter = MapRepository.Instance.GetConverter(FieldType);
if (Converter != null)
{
// Handle conversions
paramNetType = converter.DbType;
paramNetType = Converter.DbType;
}
// Get database specific DbType and store with column map in cache
DBType = repository.DbTypeBuilder.GetDbType(paramNetType);
DBType = MapRepository.Instance.DbTypeBuilder.GetDbType(paramNetType);
ColumnInfo = columnInfo;
Getter = MapRepository.Instance.ReflectionStrategy.BuildGetter(member.DeclaringType, FieldName);
Setter = MapRepository.Instance.ReflectionStrategy.BuildSetter(member.DeclaringType, FieldName);
}
public string FieldName { get; set; }
public Type FieldType { get; set; }
public Enum DBType { get; set; }
public IColumnInfo ColumnInfo { get; set; }
public GetterDelegate Getter { get; private set; }
public SetterDelegate Setter { get; private set; }
public IConverter Converter { get; private set; }
}
}

View file

@ -53,13 +53,15 @@ namespace Marr.Data.Mapping
object dbValue = reader.GetValue(ordinal);
// Handle conversions
IConverter conversion = _repos.GetConverter(dataMap.FieldType);
if (conversion != null)
if (dataMap.Converter != null)
{
dbValue = conversion.FromDB(dataMap, dbValue);
dbValue = dataMap.Converter.FromDB(dataMap, dbValue);
}
_repos.ReflectionStrategy.SetFieldValue(ent, dataMap.FieldName, dbValue);
if (dbValue != DBNull.Value)
{
dataMap.Setter(ent, dbValue);
}
}
catch (Exception ex)
{
@ -91,9 +93,9 @@ namespace Marr.Data.Mapping
var relationships = _repos.Relationships[entType];
foreach (var rel in relationships.Where(r => r.IsLazyLoaded))
{
ILazyLoaded lazyLoaded = (ILazyLoaded)rel.LazyLoaded.Clone();
var lazyLoaded = (ILazyLoaded)rel.LazyLoaded.Clone();
lazyLoaded.Prepare(dbCreate, ent);
_repos.ReflectionStrategy.SetFieldValue(ent, rel.Member.Name, lazyLoaded);
rel.Setter(ent, lazyLoaded);
}
}
}
@ -138,21 +140,18 @@ namespace Marr.Data.Mapping
param.Size = columnMap.ColumnInfo.Size;
param.Direction = columnMap.ColumnInfo.ParamDirection;
object val = _repos.ReflectionStrategy.GetFieldValue(entity, columnMap.FieldName);
object val = columnMap.Getter(entity);
param.Value = val == null ? DBNull.Value : val; // Convert nulls to DBNulls
param.Value = val ?? DBNull.Value; // Convert nulls to DBNulls
var repos = MapRepository.Instance;
IConverter conversion = repos.GetConverter(columnMap.FieldType);
if (conversion != null)
if (columnMap.Converter != null)
{
param.Value = conversion.ToDB(param.Value);
param.Value = columnMap.Converter.ToDB(param.Value);
}
// Set the appropriate DbType property depending on the parameter type
// Note: the columnMap.DBType property was set when the ColumnMap was created
repos.DbTypeBuilder.SetDbType(param, columnMap.DBType);
MapRepository.Instance.DbTypeBuilder.SetDbType(param, columnMap.DBType);
_db.Command.Parameters.Add(param);
}
@ -166,7 +165,7 @@ namespace Marr.Data.Mapping
foreach (ColumnMap dataMap in mappings)
{
object output = _db.Command.Parameters[dataMap.ColumnInfo.Name].Value;
_repos.ReflectionStrategy.SetFieldValue(entity, dataMap.FieldName, output);
dataMap.Setter(entity, output);
}
}
@ -177,7 +176,7 @@ namespace Marr.Data.Mapping
{
foreach (ColumnMap dataMap in mappings)
{
_repos.ReflectionStrategy.SetFieldValue(entity, dataMap.FieldName, Convert.ChangeType(value, dataMap.FieldType));
dataMap.Setter(entity, Convert.ChangeType(value, dataMap.FieldType));
}
}

View file

@ -14,17 +14,13 @@ You should have received a copy of the GNU Lesser General Public
License along with this library. If not, see <http://www.gnu.org/licenses/>. */
using System;
using System.Collections.Generic;
using System.Text;
using System.Reflection;
using Marr.Data.Reflection;
namespace Marr.Data.Mapping
{
public class Relationship
{
private IRelationshipInfo _relationshipInfo;
private MemberInfo _member;
private ILazyLoaded _lazyLoaded;
public Relationship(MemberInfo member)
: this(member, new RelationshipInfo())
@ -32,14 +28,14 @@ namespace Marr.Data.Mapping
public Relationship(MemberInfo member, IRelationshipInfo relationshipInfo)
{
_member = member;
Member = member;
Type memberType = ReflectionHelper.GetMemberType(member);
MemberType = ReflectionHelper.GetMemberType(member);
// Try to determine the RelationshipType
if (relationshipInfo.RelationType == RelationshipTypes.AutoDetect)
{
if (typeof(System.Collections.ICollection).IsAssignableFrom(memberType))
if (typeof(System.Collections.ICollection).IsAssignableFrom(MemberType))
{
relationshipInfo.RelationType = RelationshipTypes.Many;
}
@ -54,67 +50,48 @@ namespace Marr.Data.Mapping
{
if (relationshipInfo.RelationType == RelationshipTypes.Many)
{
if (memberType.IsGenericType)
if (MemberType.IsGenericType)
{
// Assume a Collection<T> or List<T> and return T
relationshipInfo.EntityType = memberType.GetGenericArguments()[0];
relationshipInfo.EntityType = MemberType.GetGenericArguments()[0];
}
else
{
throw new ArgumentException(string.Format(
"The DataMapper could not determine the RelationshipAttribute EntityType for {0}.",
memberType.Name));
MemberType.Name));
}
}
else
{
relationshipInfo.EntityType = memberType;
relationshipInfo.EntityType = MemberType;
}
}
_relationshipInfo = relationshipInfo;
RelationshipInfo = relationshipInfo;
Setter = MapRepository.Instance.ReflectionStrategy.BuildSetter(member.DeclaringType, member.Name);
}
public IRelationshipInfo RelationshipInfo
{
get { return _relationshipInfo; }
}
public IRelationshipInfo RelationshipInfo { get; private set; }
public MemberInfo Member
{
get { return _member; }
}
public MemberInfo Member { get; private set; }
public Type MemberType
{
get
{
// Assumes that a relationship can only have a member type of Field or Property
if (Member.MemberType == MemberTypes.Field)
return (Member as FieldInfo).FieldType;
else
return (Member as PropertyInfo).PropertyType;
}
}
public Type MemberType { get; private set; }
public bool IsLazyLoaded
{
get
{
return _lazyLoaded != null;
return LazyLoaded != null;
}
}
public ILazyLoaded LazyLoaded
{
get
{
return _lazyLoaded;
}
set
{
_lazyLoaded = value;
}
}
public ILazyLoaded LazyLoaded { get; set; }
public GetterDelegate Getter { get; set; }
public SetterDelegate Setter { get; set; }
}
}