diff --git a/appveyor.yml b/appveyor.yml index 9a38b206c..71594b38f 100644 --- a/appveyor.yml +++ b/appveyor.yml @@ -1,3 +1,5 @@ +os: Visual Studio 2015 + build: project: SQLite.Net.OSS.sln diff --git a/src/ReflectionService.cs b/src/ReflectionService.cs new file mode 100644 index 000000000..0a4fc4587 --- /dev/null +++ b/src/ReflectionService.cs @@ -0,0 +1,33 @@ +using System; +using System.Collections.Generic; +using System.Linq; +using System.Linq.Expressions; +using System.Reflection; +using SQLite.Net.Interop; + +namespace SQLite.Net.Platform { + public abstract class ReflectionService : IReflectionService { + protected internal ReflectionService() { } + + public IEnumerable GetPublicInstanceProperties(Type mappedType) { + return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); + } + + public IEnumerable GetDecoratedPrivateInstanceProperties(Type mappedType, Type attributeType) { + return mappedType.GetProperties(BindingFlags.NonPublic | BindingFlags.Instance | BindingFlags.SetProperty) + .Where(x => x.GetSetMethod(false) != null || x.GetCustomAttribute(attributeType) != null); + } + + public object GetMemberValue(object obj, Expression expr, MemberInfo member) { + if (member.MemberType == MemberTypes.Property) { + var m = (PropertyInfo)member; + return m.GetValue(obj, null); + } + if (member.MemberType == MemberTypes.Field) { + var m = (FieldInfo)member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.MemberType); + } + } +} \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs b/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs index 979d004fc..05629b960 100644 --- a/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs +++ b/src/SQLite.Net.Platform.Generic/ReflectionServiceGeneric.cs @@ -1,31 +1,11 @@ using System; using System.Collections.Generic; +using System.Linq; using System.Linq.Expressions; using System.Reflection; using SQLite.Net.Interop; namespace SQLite.Net.Platform.Generic { - public class ReflectionServiceGeneric : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceGeneric : ReflectionService { } } diff --git a/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj b/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj index f4f1a364d..d184478f2 100644 --- a/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj +++ b/src/SQLite.Net.Platform.Generic/SQLite.Net.Platform.Generic.csproj @@ -37,6 +37,9 @@ Properties\GlobalAssemblyInfo.cs + + ReflectionService.cs + diff --git a/src/SQLite.Net.Platform.OSX/ReflectionServiceOSX.cs b/src/SQLite.Net.Platform.OSX/ReflectionServiceOSX.cs index eb61c7c21..e2bde735f 100644 --- a/src/SQLite.Net.Platform.OSX/ReflectionServiceOSX.cs +++ b/src/SQLite.Net.Platform.OSX/ReflectionServiceOSX.cs @@ -1,31 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using SQLite.Net.Interop; - -namespace SQLite.Net.Platform.OSX +namespace SQLite.Net.Platform.OSX { - public class ReflectionServiceOSX : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceOSX : ReflectionService { } } diff --git a/src/SQLite.Net.Platform.OSX/SQLite.Net.Platform.OSX.csproj b/src/SQLite.Net.Platform.OSX/SQLite.Net.Platform.OSX.csproj index 741864c0d..32263d497 100644 --- a/src/SQLite.Net.Platform.OSX/SQLite.Net.Platform.OSX.csproj +++ b/src/SQLite.Net.Platform.OSX/SQLite.Net.Platform.OSX.csproj @@ -43,6 +43,9 @@ + + ReflectionService.cs + @@ -60,10 +63,10 @@ --> - - - - + + + + PreserveNewest @@ -81,4 +84,4 @@ SQLite.Net - + \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs b/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs index 2373274d3..6b79fe6b5 100644 --- a/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs +++ b/src/SQLite.Net.Platform.Win32/ReflectionServiceWin32.cs @@ -1,31 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using SQLite.Net.Interop; - -namespace SQLite.Net.Platform.Win32 +namespace SQLite.Net.Platform.Win32 { - public class ReflectionServiceWin32 : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceWin32 : ReflectionService { } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj b/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj index 4a6136523..1a8d629a3 100644 --- a/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj +++ b/src/SQLite.Net.Platform.Win32/SQLite.Net.Platform.Win32.csproj @@ -48,6 +48,9 @@ Properties\GlobalAssemblyInfo.cs + + ReflectionService.cs + diff --git a/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs b/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs index 2ba36382b..fca194972 100644 --- a/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs +++ b/src/SQLite.Net.Platform.WinRT/ReflectionServiceWinRT.cs @@ -10,27 +10,39 @@ namespace SQLite.Net.Platform.WinRT public class ReflectionServiceWinRT : IReflectionService { public IEnumerable GetPublicInstanceProperties(Type mappedType) + { + if (mappedType == null) throw new ArgumentNullException(nameof(mappedType)); + + return from p in mappedType.GetRuntimeProperties() + where + ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || + (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) + select p; + } + + public IEnumerable GetDecoratedPrivateInstanceProperties(Type mappedType, Type attributeType) { return from p in mappedType.GetRuntimeProperties() - where - ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || - (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) - select p; + where ( + (p.GetMethod != null && p.GetMethod.IsPrivate) || (p.SetMethod != null && p.SetMethod.IsPrivate) || + p.GetCustomAttribute(attributeType) != null + ) + select p; } public object GetMemberValue(object obj, Expression expr, MemberInfo member) { - if (member is PropertyInfo) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member is FieldInfo) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.DeclaringType); + if (member is PropertyInfo) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member is FieldInfo) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.DeclaringType); } } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs b/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs index 1ade84ad3..605b6f978 100644 --- a/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs +++ b/src/SQLite.Net.Platform.WindowsPhone8/ReflectionServiceWP8.cs @@ -8,32 +8,41 @@ namespace SQLite.Net.Platform.WindowsPhone8 { public class ReflectionServiceWP8 : IReflectionService - { + { public IEnumerable GetPublicInstanceProperties(Type mappedType) { - if (mappedType == null) - { - throw new ArgumentNullException("mappedType"); - } + if (mappedType == null) throw new ArgumentNullException(nameof(mappedType)); + + return from p in mappedType.GetRuntimeProperties() + where + ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || + (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) + select p; + } + + public IEnumerable GetDecoratedPrivateInstanceProperties(Type mappedType, Type attributeType) + { return from p in mappedType.GetRuntimeProperties() - where - ((p.GetMethod != null && p.GetMethod.IsPublic) || (p.SetMethod != null && p.SetMethod.IsPublic) || - (p.GetMethod != null && p.GetMethod.IsStatic) || (p.SetMethod != null && p.SetMethod.IsStatic)) - select p; + where ( + (p.GetMethod != null && p.GetMethod.IsPrivate) || (p.SetMethod != null && p.SetMethod.IsPrivate) || + p.GetCustomAttribute(attributeType) != null + ) + select p; } public object GetMemberValue(object obj, Expression expr, MemberInfo member) { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - return Expression.Lambda(expr).Compile().DynamicInvoke(); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); + if (member is PropertyInfo) + { + var m = (PropertyInfo) member; + return m.GetValue(obj, null); + } + if (member is FieldInfo) + { + var m = (FieldInfo) member; + return m.GetValue(obj); + } + throw new NotSupportedException("MemberExpr: " + member.DeclaringType); } } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs b/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs index f91597d17..7e9d60db3 100644 --- a/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs +++ b/src/SQLite.Net.Platform.XamarinAndroid/ReflectionServiceAndroid.cs @@ -1,31 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using SQLite.Net.Interop; - -namespace SQLite.Net.Platform.XamarinAndroid +namespace SQLite.Net.Platform.XamarinAndroid { - public class ReflectionServiceAndroid : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceAndroid : ReflectionService { } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj b/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj index 0b8acb05c..1fdf4c580 100644 --- a/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj +++ b/src/SQLite.Net.Platform.XamarinAndroid/SQLite.Net.Platform.XamarinAndroid.csproj @@ -46,6 +46,9 @@ Properties\GlobalAssemblyInfo.cs + + ReflectionService.cs + diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs index ec69f0ef1..ee41fffe9 100644 --- a/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/ReflectionServiceIOS.cs @@ -1,31 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using SQLite.Net.Interop; - -namespace SQLite.Net.Platform.XamarinIOS +namespace SQLite.Net.Platform.XamarinIOS { - public class ReflectionServiceIOS : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceIOS : ReflectionService { } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj index b4a74863d..8d0f8738d 100644 --- a/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj +++ b/src/SQLite.Net.Platform.XamarinIOS.Unified/SQLite.Net.Platform.XamarinIOS.Unified.csproj @@ -1,4 +1,4 @@ - + Debug @@ -35,6 +35,9 @@ + + ReflectionService.cs + Properties\GlobalAssemblyInfo.cs diff --git a/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs b/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs index ec69f0ef1..ee41fffe9 100644 --- a/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs +++ b/src/SQLite.Net.Platform.XamarinIOS/ReflectionServiceIOS.cs @@ -1,31 +1,4 @@ -using System; -using System.Collections.Generic; -using System.Linq.Expressions; -using System.Reflection; -using SQLite.Net.Interop; - -namespace SQLite.Net.Platform.XamarinIOS +namespace SQLite.Net.Platform.XamarinIOS { - public class ReflectionServiceIOS : IReflectionService - { - public IEnumerable GetPublicInstanceProperties(Type mappedType) - { - return mappedType.GetProperties(BindingFlags.Public | BindingFlags.Instance | BindingFlags.SetProperty); - } - - public object GetMemberValue(object obj, Expression expr, MemberInfo member) - { - if (member.MemberType == MemberTypes.Property) - { - var m = (PropertyInfo) member; - return m.GetValue(obj, null); - } - if (member.MemberType == MemberTypes.Field) - { - var m = (FieldInfo) member; - return m.GetValue(obj); - } - throw new NotSupportedException("MemberExpr: " + member.MemberType); - } - } + public class ReflectionServiceIOS : ReflectionService { } } \ No newline at end of file diff --git a/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj b/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj index ac4638d3e..5b29ee7f0 100644 --- a/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj +++ b/src/SQLite.Net.Platform.XamarinIOS/SQLite.Net.Platform.XamarinIOS.csproj @@ -37,6 +37,9 @@ Properties\GlobalAssemblyInfo.cs + + ReflectionService.cs + diff --git a/src/SQLite.Net/Attributes/ColumnAttribute.cs b/src/SQLite.Net/Attributes/ColumnAttribute.cs index f666b217a..a2bebcea3 100644 --- a/src/SQLite.Net/Attributes/ColumnAttribute.cs +++ b/src/SQLite.Net/Attributes/ColumnAttribute.cs @@ -29,6 +29,8 @@ namespace SQLite.Net.Attributes [AttributeUsage(AttributeTargets.Property)] public class ColumnAttribute : Attribute { + public ColumnAttribute() { } + public ColumnAttribute(string name) { Name = name; diff --git a/src/SQLite.Net/Interop/IReflectionService.cs b/src/SQLite.Net/Interop/IReflectionService.cs index 246f6fbe4..00804a455 100644 --- a/src/SQLite.Net/Interop/IReflectionService.cs +++ b/src/SQLite.Net/Interop/IReflectionService.cs @@ -31,6 +31,7 @@ namespace SQLite.Net.Interop public interface IReflectionService { IEnumerable GetPublicInstanceProperties(Type mappedType); + IEnumerable GetDecoratedPrivateInstanceProperties(Type mappedType, Type attributeType); object GetMemberValue(object obj, Expression expr, MemberInfo member); } } \ No newline at end of file diff --git a/src/SQLite.Net/SQLiteConnection.cs b/src/SQLite.Net/SQLiteConnection.cs index be0946530..63d18e9f4 100644 --- a/src/SQLite.Net/SQLiteConnection.cs +++ b/src/SQLite.Net/SQLiteConnection.cs @@ -310,10 +310,13 @@ public TableMapping GetMapping(Type type, CreateFlags createFlags = CreateFlags. private TableMapping CreateAndSetMapping(Type type, CreateFlags createFlags, IDictionary mapTable) { - var props = Platform.ReflectionService.GetPublicInstanceProperties(type); + var props = Platform.ReflectionService.GetPublicInstanceProperties(type).Union( + Platform.ReflectionService.GetDecoratedPrivateInstanceProperties(type, typeof(ColumnAttribute)) + ); + var map = new TableMapping(type, props, createFlags); - mapTable[type.FullName] = map; - return map; + mapTable[type.FullName] = map; + return map; } /// diff --git a/src/SQLite.Net/TableMapping.cs b/src/SQLite.Net/TableMapping.cs index c14a5081b..56e3e57a3 100644 --- a/src/SQLite.Net/TableMapping.cs +++ b/src/SQLite.Net/TableMapping.cs @@ -140,7 +140,7 @@ public Column(PropertyInfo prop, CreateFlags createFlags = CreateFlags.None) prop.GetCustomAttributes(true).FirstOrDefault(); _prop = prop; - Name = colAttr == null ? prop.Name : colAttr.Name; + Name = colAttr?.Name ?? prop.Name; //If this type is Nullable then Nullable.GetUnderlyingType returns the T, otherwise it returns null, so get the actual type instead ColumnType = Nullable.GetUnderlyingType(prop.PropertyType) ?? prop.PropertyType; Collation = Orm.Collation(prop); diff --git a/tests/MappingTest.cs b/tests/MappingTest.cs index 811b7c593..98ce2e679 100644 --- a/tests/MappingTest.cs +++ b/tests/MappingTest.cs @@ -92,5 +92,28 @@ public void CanUseSubtypeOfTableAttribute() Assert.That(numCats,Is.EqualTo(1), "The resulting num cats should be 1."); } + + [Test] + public void CanUsePrivateDecoratedProperties() + { + var db = new TestDb(); + + db.CreateTable(); + + TableMapping mapping = db.GetMapping(); + + Assert.AreEqual(mapping.Columns.Length, 2); + + Assert.AreEqual("Public", mapping.Columns[0].Name); + Assert.AreEqual("Private", mapping.Columns[1].Name); + } + + + [Table("accessor")] + public class AccessorTable { + public int Public { get; set; } + [Column] + private int Private { get; set; } + } } } \ No newline at end of file