From ace98831c77251c0c6aa3f201d7b155e26b0c654 Mon Sep 17 00:00:00 2001 From: "kay.one" Date: Sun, 2 Jun 2013 20:15:56 -0700 Subject: [PATCH] using compiled delegate instead of reflection in Marr --- Marr.Data/EntityGraph.cs | 26 ++-- Marr.Data/MapRepository.cs | 7 +- Marr.Data/Mapping/ColumnMap.cs | 27 ++-- Marr.Data/Mapping/MappingHelper.cs | 31 ++-- Marr.Data/Mapping/Relationship.cs | 65 +++----- Marr.Data/Marr.Data.csproj | 8 - Marr.Data/Parameters/ParameterChainMethods.cs | 3 - .../Reflection/CachedReflectionStrategy.cs | 99 ------------ Marr.Data/Reflection/IReflectionStrategy.cs | 11 +- .../Reflection/SimpleReflectionStrategy.cs | 144 +++++++++++------- NzbDrone.Core.Test/Framework/DbTest.cs | 1 + NzbDrone.Core.Test/NzbDrone.Core.Test.csproj | 1 + NzbDrone.Core/Datastore/DbFactory.cs | 4 +- .../Datastore/DelegateReflectionStrategy.cs | 128 ---------------- NzbDrone.Core/Datastore/TableMapping.cs | 2 - NzbDrone.Core/NzbDrone.Core.csproj | 1 - 16 files changed, 170 insertions(+), 388 deletions(-) delete mode 100644 Marr.Data/Reflection/CachedReflectionStrategy.cs delete mode 100644 NzbDrone.Core/Datastore/DelegateReflectionStrategy.cs diff --git a/Marr.Data/EntityGraph.cs b/Marr.Data/EntityGraph.cs index ce9e55e9f..3604389e7 100644 --- a/Marr.Data/EntityGraph.cs +++ b/Marr.Data/EntityGraph.cs @@ -74,7 +74,7 @@ namespace Marr.Data { _columns = _repos.GetColumns(entityType); } - + _relationships = _repos.GetRelationships(entityType); _children = new List(); Member = relationship != null ? relationship.Member : null; @@ -161,7 +161,7 @@ namespace Marr.Data { get { return _children; } } - + /// /// Adds an entity to the appropriate place in the object graph. /// @@ -184,13 +184,13 @@ namespace Marr.Data } else // RelationTypes.One { - _repos.ReflectionStrategy.SetFieldValue(_parent._entity, _relationship.Member.Name, entityInstance); + _relationship.Setter(_parent._entity, entityInstance); } EntityReference entityRef = new EntityReference(entityInstance); _entityReferences.Add(GroupingKeyColumns.GroupingKey, entityRef); - InitOneToManyChildLists(entityRef); + InitOneToManyChildLists(entityRef); } /// @@ -199,9 +199,9 @@ namespace Marr.Data public void AddParentReference() { var parentReference = FindParentReference(); - _repos.ReflectionStrategy.SetFieldValue(_parent._entity, _relationship.Member.Name, parentReference); + _relationship.Setter(_parent._entity, parentReference); } - + /// /// Concatenates the values of the GroupingKeys property and compares them /// against the LastKeyGroup property. Returns true if the values are different, @@ -296,8 +296,8 @@ namespace Marr.Data try { IList list = (IList)_repos.ReflectionStrategy.CreateInstance(relationship.MemberType); - _repos.ReflectionStrategy.SetFieldValue(entityRef.Entity, relationship.Member.Name, list); - + relationship.Setter(entityRef.Entity, list); + // Save a reference to each 1-M list entityRef.AddChildList(relationship.Member.Name, list); } @@ -398,13 +398,13 @@ public struct KeyGroupInfo _hasNullKey = hasNullKey; } - public string GroupingKey - { - get { return _groupingKey; } + public string GroupingKey + { + get { return _groupingKey; } } - public bool HasNullKey + public bool HasNullKey { - get { return _hasNullKey; } + get { return _hasNullKey; } } } diff --git a/Marr.Data/MapRepository.cs b/Marr.Data/MapRepository.cs index c60dc4c09..0193f60c4 100644 --- a/Marr.Data/MapRepository.cs +++ b/Marr.Data/MapRepository.cs @@ -53,8 +53,8 @@ namespace Marr.Data TypeConverters = new Dictionary(); // Register a default IReflectionStrategy - ReflectionStrategy = new CachedReflectionStrategy(); - + ReflectionStrategy = new SimpleReflectionStrategy(); + // Register a default type converter for Enums TypeConverters.Add(typeof(Enum), new Converters.EnumStringConverter()); @@ -180,7 +180,7 @@ namespace Marr.Data return Relationships[type]; } - + #endregion #region - Reflection Strategy - @@ -190,6 +190,7 @@ namespace Marr.Data /// 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 diff --git a/Marr.Data/Mapping/ColumnMap.cs b/Marr.Data/Mapping/ColumnMap.cs index 3ae479b4c..e971daca0 100644 --- a/Marr.Data/Mapping/ColumnMap.cs +++ b/Marr.Data/Mapping/ColumnMap.cs @@ -14,11 +14,9 @@ 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 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 /// public class ColumnMap { + /// /// Creates a column map with an empty ColumnInfo object. /// @@ -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; } } } diff --git a/Marr.Data/Mapping/MappingHelper.cs b/Marr.Data/Mapping/MappingHelper.cs index c9b6def31..5253c4548 100644 --- a/Marr.Data/Mapping/MappingHelper.cs +++ b/Marr.Data/Mapping/MappingHelper.cs @@ -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); - - param.Value = val == null ? DBNull.Value : val; // Convert nulls to DBNulls + object val = columnMap.Getter(entity); - var repos = MapRepository.Instance; + param.Value = val ?? DBNull.Value; // Convert nulls to DBNulls - 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)); } } diff --git a/Marr.Data/Mapping/Relationship.cs b/Marr.Data/Mapping/Relationship.cs index f39715292..a28821f44 100644 --- a/Marr.Data/Mapping/Relationship.cs +++ b/Marr.Data/Mapping/Relationship.cs @@ -14,17 +14,13 @@ 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 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 or List 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; - public IRelationshipInfo RelationshipInfo - { - get { return _relationshipInfo; } - } - public MemberInfo Member - { - get { return _member; } - } - 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; - } + Setter = MapRepository.Instance.ReflectionStrategy.BuildSetter(member.DeclaringType, member.Name); } + public IRelationshipInfo RelationshipInfo { get; private set; } + + public MemberInfo Member { get; private set; } + + 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; } } } diff --git a/Marr.Data/Marr.Data.csproj b/Marr.Data/Marr.Data.csproj index c30e40535..4c39d458e 100644 --- a/Marr.Data/Marr.Data.csproj +++ b/Marr.Data/Marr.Data.csproj @@ -39,17 +39,10 @@ 4 - - False - ..\packages\fasterflect.2.1.3\lib\net40\Fasterflect.dll - 3.5 - - 3.5 - @@ -134,7 +127,6 @@ - diff --git a/Marr.Data/Parameters/ParameterChainMethods.cs b/Marr.Data/Parameters/ParameterChainMethods.cs index 9f857cbfd..c1ceef248 100644 --- a/Marr.Data/Parameters/ParameterChainMethods.cs +++ b/Marr.Data/Parameters/ParameterChainMethods.cs @@ -14,9 +14,6 @@ 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 System.Linq; -using System.Text; using System.Data; using System.Data.Common; using Marr.Data.Converters; diff --git a/Marr.Data/Reflection/CachedReflectionStrategy.cs b/Marr.Data/Reflection/CachedReflectionStrategy.cs deleted file mode 100644 index a19eff03d..000000000 --- a/Marr.Data/Reflection/CachedReflectionStrategy.cs +++ /dev/null @@ -1,99 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Reflection; -using Fasterflect; - -namespace Marr.Data.Reflection -{ - public class CachedReflectionStrategy : IReflectionStrategy - { - private static readonly Dictionary MemberCache = new Dictionary(); - private static MemberInfo GetMember(Type entityType, string name) - { - MemberInfo member; - var key = entityType.FullName + name; - if (!MemberCache.TryGetValue(key, out member)) - { - member = entityType.GetMember(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance)[0]; - MemberCache[key] = member; - } - - return member; - } - - /// - /// Sets an entity field value by name to the passed in 'val'. - /// - public void SetFieldValue(T entity, string fieldName, object val) - { - MemberInfo member = GetMember(entity.GetType(), fieldName); - - try - { - // Handle DB null values - if (val == DBNull.Value) - { - if (member.MemberType == MemberTypes.Field) - { - entity.SetFieldValue(member.Name, ReflectionHelper.GetDefaultValue(((FieldInfo)member).FieldType)); - } - else if (member.MemberType == MemberTypes.Property) - { - var pi = (PropertyInfo)member; - if (pi.CanWrite) - { - entity.SetPropertyValue(member.Name, ReflectionHelper.GetDefaultValue(((PropertyInfo)member).PropertyType)); - } - } - } - else - { - if (member.MemberType == MemberTypes.Field) - { - entity.SetFieldValue(member.Name, val); - } - else if (member.MemberType == MemberTypes.Property && ((PropertyInfo)member).CanWrite) - { - member.Set(entity, val); - } - } - } - catch (Exception ex) - { - string msg = string.Format("The DataMapper was unable to load the following field: {0}. \nDetails: {1}", fieldName, ex.Message); - throw new DataMappingException(msg, ex); - } - } - - /// - /// Gets an entity field value by name. - /// - public object GetFieldValue(object entity, string fieldName) - { - MemberInfo member = GetMember(entity.GetType(), fieldName); - - - if (member.MemberType == MemberTypes.Field) - { - return entity.GetFieldValue(member.Name); - } - - if (member.MemberType == MemberTypes.Property && ((PropertyInfo)member).CanRead) - { - return entity.GetPropertyValue(member.Name); - } - - throw new DataMappingException(string.Format("The DataMapper could not get the value for {0}.{1}.", entity.GetType().Name, fieldName)); - } - - /// - /// Instantiantes a type using the Fasterflect library for increased speed. - /// - /// - /// - public object CreateInstance(Type type) - { - return type.CreateInstance(); - } - } -} diff --git a/Marr.Data/Reflection/IReflectionStrategy.cs b/Marr.Data/Reflection/IReflectionStrategy.cs index 096d64664..e73a0bc8f 100644 --- a/Marr.Data/Reflection/IReflectionStrategy.cs +++ b/Marr.Data/Reflection/IReflectionStrategy.cs @@ -1,14 +1,17 @@ using System; -using System.Collections.Generic; -using System.Linq; -using System.Text; namespace Marr.Data.Reflection { public interface IReflectionStrategy { - void SetFieldValue(T entity, string fieldName, object val); object GetFieldValue(object entity, string fieldName); + + GetterDelegate BuildGetter(Type type, string memberName); + SetterDelegate BuildSetter(Type type, string memberName); + object CreateInstance(Type type); } + + public delegate void SetterDelegate(object instance, object value); + public delegate object GetterDelegate(object instance); } diff --git a/Marr.Data/Reflection/SimpleReflectionStrategy.cs b/Marr.Data/Reflection/SimpleReflectionStrategy.cs index 8e6a964ca..9e741b013 100644 --- a/Marr.Data/Reflection/SimpleReflectionStrategy.cs +++ b/Marr.Data/Reflection/SimpleReflectionStrategy.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using System.Linq.Expressions; using System.Reflection; namespace Marr.Data.Reflection @@ -8,6 +9,8 @@ namespace Marr.Data.Reflection { private static readonly Dictionary MemberCache = new Dictionary(); + private static readonly Dictionary GetterCache = new Dictionary(); + private static readonly Dictionary SetterCache = new Dictionary(); private static MemberInfo GetMember(Type entityType, string name) @@ -23,54 +26,6 @@ namespace Marr.Data.Reflection return member; } - /// - /// Sets an entity field value by name to the passed in 'val'. - /// - public void SetFieldValue(T entity, string fieldName, object val) - { - var member = GetMember(entity.GetType(), fieldName); - - try - { - // Handle DB null values - if (val == DBNull.Value) - { - if (member.MemberType == MemberTypes.Field) - { - (member as FieldInfo).SetValue(entity, - ReflectionHelper.GetDefaultValue((member as FieldInfo).FieldType)); - } - else if (member.MemberType == MemberTypes.Property) - { - var pi = (member as PropertyInfo); - if (pi.CanWrite) - (member as PropertyInfo).SetValue(entity, - ReflectionHelper.GetDefaultValue( - (member as PropertyInfo).PropertyType), null); - - } - } - else - { - if (member.MemberType == MemberTypes.Field) - (member as FieldInfo).SetValue(entity, val); - - else if (member.MemberType == MemberTypes.Property) - { - var pi = (member as PropertyInfo); - if (pi.CanWrite) - (member as PropertyInfo).SetValue(entity, val, null); - - } - } - } - catch (Exception ex) - { - string msg = string.Format("The DataMapper was unable to load the following field: {0}. \nDetails: {1}", fieldName, ex.Message); - throw new DataMappingException(msg, ex); - } - } - /// /// Gets an entity field value by name. /// @@ -84,14 +39,14 @@ namespace Marr.Data.Reflection } if (member.MemberType == MemberTypes.Property) { - if ((member as PropertyInfo).CanRead) - return (member as PropertyInfo).GetValue(entity, null); + return BuildGetter(entity.GetType(), fieldName)(entity); } throw new DataMappingException(string.Format("The DataMapper could not get the value for {0}.{1}.", entity.GetType().Name, fieldName)); } + /// - /// Instantiantes a type using the FastReflector library for increased speed. + /// Instantiates a type using the FastReflector library for increased speed. /// /// /// @@ -99,5 +54,92 @@ namespace Marr.Data.Reflection { return Activator.CreateInstance(type); } + + + + + public GetterDelegate BuildGetter(Type type, string memberName) + { + GetterDelegate getter; + var key = type.FullName + memberName; + if (!GetterCache.TryGetValue(key, out getter)) + { + getter = GetPropertyGetter((PropertyInfo)GetMember(type, memberName)); + } + + return getter; + } + + public SetterDelegate BuildSetter(Type type, string memberName) + { + SetterDelegate setter; + var key = type.FullName + memberName; + if (!SetterCache.TryGetValue(key, out setter)) + { + setter = GetPropertySetter((PropertyInfo)GetMember(type, memberName)); + } + + return setter; + } + + + private static SetterDelegate GetPropertySetter(PropertyInfo propertyInfo) + { + var propertySetMethod = propertyInfo.GetSetMethod(); + if (propertySetMethod == null) return null; + +#if NO_EXPRESSIONS + return (o, convertedValue) => + { + propertySetMethod.Invoke(o, new[] { convertedValue }); + return; + }; +#else + var instance = Expression.Parameter(typeof(object), "i"); + var argument = Expression.Parameter(typeof(object), "a"); + + var instanceParam = Expression.Convert(instance, propertyInfo.DeclaringType); + var valueParam = Expression.Convert(argument, propertyInfo.PropertyType); + + var setterCall = Expression.Call(instanceParam, propertyInfo.GetSetMethod(), valueParam); + + return Expression.Lambda(setterCall, instance, argument).Compile(); +#endif + } + + private static GetterDelegate GetPropertyGetter(PropertyInfo propertyInfo) + { + + var getMethodInfo = propertyInfo.GetGetMethod(); + if (getMethodInfo == null) return null; + +#if NO_EXPRESSIONS + return o => propertyInfo.GetGetMethod().Invoke(o, new object[] { }); +#else + try + { + var oInstanceParam = Expression.Parameter(typeof(object), "oInstanceParam"); + var instanceParam = Expression.Convert(oInstanceParam, propertyInfo.DeclaringType); + + var exprCallPropertyGetFn = Expression.Call(instanceParam, getMethodInfo); + var oExprCallPropertyGetFn = Expression.Convert(exprCallPropertyGetFn, typeof(object)); + + var propertyGetFn = Expression.Lambda + ( + oExprCallPropertyGetFn, + oInstanceParam + ).Compile(); + + return propertyGetFn; + + } + catch (Exception ex) + { + Console.Write(ex.Message); + throw; + } +#endif + } + } } diff --git a/NzbDrone.Core.Test/Framework/DbTest.cs b/NzbDrone.Core.Test/Framework/DbTest.cs index b1f0bc6fd..b55cd1c17 100644 --- a/NzbDrone.Core.Test/Framework/DbTest.cs +++ b/NzbDrone.Core.Test/Framework/DbTest.cs @@ -11,6 +11,7 @@ using NzbDrone.Core.Datastore.Migration.Framework; namespace NzbDrone.Core.Test.Framework { + [Category("DbTest")] public abstract class DbTest : DbTest where TSubject : class where TModel : ModelBase, new() diff --git a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj index d8bd1b5d5..3f4e1c03c 100644 --- a/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj +++ b/NzbDrone.Core.Test/NzbDrone.Core.Test.csproj @@ -123,6 +123,7 @@ + diff --git a/NzbDrone.Core/Datastore/DbFactory.cs b/NzbDrone.Core/Datastore/DbFactory.cs index bb7a8ad43..7b1fd6318 100644 --- a/NzbDrone.Core/Datastore/DbFactory.cs +++ b/NzbDrone.Core/Datastore/DbFactory.cs @@ -18,6 +18,7 @@ namespace NzbDrone.Core.Datastore static DbFactory() { + MapRepository.Instance.ReflectionStrategy = new SimpleReflectionStrategy(); TableMapping.Map(); } @@ -32,9 +33,6 @@ namespace NzbDrone.Core.Datastore _migrationController.MigrateToLatest(connectionString, migrationType); - - MapRepository.Instance.ReflectionStrategy = new DelegateReflectionStrategy(); - return new Database(() => { var dataMapper = new DataMapper(SQLiteFactory.Instance, connectionString) diff --git a/NzbDrone.Core/Datastore/DelegateReflectionStrategy.cs b/NzbDrone.Core/Datastore/DelegateReflectionStrategy.cs deleted file mode 100644 index 4afb28109..000000000 --- a/NzbDrone.Core/Datastore/DelegateReflectionStrategy.cs +++ /dev/null @@ -1,128 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using Marr.Data.Reflection; - -namespace NzbDrone.Core.Datastore -{ - public class DelegateReflectionStrategy : IReflectionStrategy - { - private static readonly Dictionary SetterCache = new Dictionary(); - private static readonly Dictionary GetterCache = new Dictionary(); - private static readonly IReflectionStrategy readStrat = new SimpleReflectionStrategy(); - - private static PropertySetterDelegate SetterFunction(Type entityType, string name) - { - PropertySetterDelegate setter; - var key = string.Concat(entityType.FullName, name); - if (!SetterCache.TryGetValue(key, out setter)) - { - var setterMember = entityType.GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - setter = setterMember.GetPropertySetterFn(); - SetterCache[key] = setter; - } - - return setter; - } - - - private static PropertyGetterDelegate GetterFunction(Type entityType, string name) - { - PropertyGetterDelegate getter; - var key = string.Concat(entityType.FullName, name); - if (!GetterCache.TryGetValue(key, out getter)) - { - var propertyInfo = entityType.GetProperty(name, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance); - getter = propertyInfo.GetPropertyGetterFn(); - GetterCache[key] = getter; - } - - return getter; - } - - - public void SetFieldValue(T entity, string fieldName, object val) - { - SetterFunction(entity.GetType(), fieldName)(entity, val); - } - - public object GetFieldValue(object entity, string fieldName) - { - return readStrat.GetFieldValue(entity, fieldName); - } - - public object CreateInstance(Type type) - { - return Activator.CreateInstance(type); - } - - - - } - - public delegate void PropertySetterDelegate(object instance, object value); - public delegate object PropertyGetterDelegate(object instance); - - public static class PropertyInvoker - { - public static PropertySetterDelegate GetPropertySetterFn(this PropertyInfo propertyInfo) - { - var propertySetMethod = propertyInfo.GetSetMethod(); - if (propertySetMethod == null) return null; - -#if NO_EXPRESSIONS - return (o, convertedValue) => - { - propertySetMethod.Invoke(o, new[] { convertedValue }); - return; - }; -#else - var instance = Expression.Parameter(typeof(object), "i"); - var argument = Expression.Parameter(typeof(object), "a"); - - var instanceParam = Expression.Convert(instance, propertyInfo.DeclaringType); - var valueParam = Expression.Convert(argument, propertyInfo.PropertyType); - - var setterCall = Expression.Call(instanceParam, propertyInfo.GetSetMethod(), valueParam); - - return Expression.Lambda(setterCall, instance, argument).Compile(); -#endif - } - - public static PropertyGetterDelegate GetPropertyGetterFn(this PropertyInfo propertyInfo) - { - var getMethodInfo = propertyInfo.GetGetMethod(); - if (getMethodInfo == null) return null; - -#if NO_EXPRESSIONS - return o => propertyInfo.GetGetMethod().Invoke(o, new object[] { }); -#else - try - { - var oInstanceParam = Expression.Parameter(typeof(object), "oInstanceParam"); - var instanceParam = Expression.Convert(oInstanceParam, propertyInfo.DeclaringType); - - var exprCallPropertyGetFn = Expression.Call(instanceParam, getMethodInfo); - var oExprCallPropertyGetFn = Expression.Convert(exprCallPropertyGetFn, typeof(object)); - - var propertyGetFn = Expression.Lambda - ( - oExprCallPropertyGetFn, - oInstanceParam - ).Compile(); - - return propertyGetFn; - - } - catch (Exception ex) - { - Console.Write(ex.Message); - throw; - } -#endif - } - } - - -} \ No newline at end of file diff --git a/NzbDrone.Core/Datastore/TableMapping.cs b/NzbDrone.Core/Datastore/TableMapping.cs index 4d2090ac6..e461dbf5c 100644 --- a/NzbDrone.Core/Datastore/TableMapping.cs +++ b/NzbDrone.Core/Datastore/TableMapping.cs @@ -3,8 +3,6 @@ using System.Collections.Generic; using System.Linq; using Marr.Data; using Marr.Data.Mapping; -using NzbDrone.Common; -using NzbDrone.Common.Serializer; using NzbDrone.Core.Configuration; using NzbDrone.Core.DataAugmentation.Scene; using NzbDrone.Core.Datastore.Converters; diff --git a/NzbDrone.Core/NzbDrone.Core.csproj b/NzbDrone.Core/NzbDrone.Core.csproj index 412d9adc8..20ef8261e 100644 --- a/NzbDrone.Core/NzbDrone.Core.csproj +++ b/NzbDrone.Core/NzbDrone.Core.csproj @@ -220,7 +220,6 @@ -