using System; using System.Collections.Generic; using System.Linq; using System.Linq.Expressions; using System.Reflection; using Dapper; using NzbDrone.Common.Reflection; namespace NzbDrone.Core.Datastore { public static class MappingExtensions { public static PropertyInfo GetMemberName(this Expression> member) { var memberExpression = member.Body as MemberExpression; if (memberExpression == null) { memberExpression = (member.Body as UnaryExpression).Operand as MemberExpression; } return (PropertyInfo)memberExpression.Member; } } public class TableMapper { public TableMapper() { IgnoreList = new Dictionary>(); TableMap = new Dictionary(); } public Dictionary> IgnoreList { get; set; } public Dictionary TableMap { get; set; } public ColumnMapper Entity(string tableName) { TableMap.Add(typeof(TEntity), tableName); if (IgnoreList.TryGetValue(typeof(TEntity), out var list)) { return new ColumnMapper(list); } list = new List(); IgnoreList[typeof(TEntity)] = list; return new ColumnMapper(list); } public List ExcludeProperties(Type x) { return IgnoreList.ContainsKey(x) ? IgnoreList[x] : new List(); } public string TableNameMapping(Type x) { return TableMap.ContainsKey(x) ? TableMap[x] : null; } } public class ColumnMapper { private readonly List _ignoreList; public ColumnMapper(List ignoreList) { _ignoreList = ignoreList; } public ColumnMapper AutoMapPropertiesWhere(Func predicate) { Type entityType = typeof(T); var properties = entityType.GetProperties(); _ignoreList.AddRange(properties.Where(x => !predicate(x))); return this; } public ColumnMapper RegisterModel() { return AutoMapPropertiesWhere(IsMappableProperty); } public ColumnMapper Ignore(Expression> property) { _ignoreList.Add(property.GetMemberName()); return this; } public static bool IsMappableProperty(MemberInfo memberInfo) { var propertyInfo = memberInfo as PropertyInfo; if (propertyInfo == null) { return false; } if (!propertyInfo.IsReadable() || !propertyInfo.IsWritable()) { return false; } // This is a bit of a hack but is the only way to see if a type has a handler set in Dapper #pragma warning disable 618 SqlMapper.LookupDbType(propertyInfo.PropertyType, "", false, out var handler); #pragma warning restore 618 if (propertyInfo.PropertyType.IsSimpleType() || handler != null) { return true; } return false; } } }