From: <fab...@us...> - 2011-04-10 19:27:43
|
Revision: 5654 http://nhibernate.svn.sourceforge.net/nhibernate/?rev=5654&view=rev Author: fabiomaulo Date: 2011-04-10 19:27:37 +0000 (Sun, 10 Apr 2011) Log Message: ----------- SimpleModelInspector with default pattern to discover Persistent properties Modified Paths: -------------- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/AccessorPropertyMapper.cs trunk/nhibernate/src/NHibernate/Mapping/ByCode/SimpleModelInspector.cs trunk/nhibernate/src/NHibernate/NHibernate.csproj trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj Added Paths: ----------- trunk/nhibernate/src/NHibernate/Mapping/ByCode/PropertyToField.cs trunk/nhibernate/src/NHibernate.Test/MappingByCode/MixAutomapping/PropertiesExclusionTests.cs Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/AccessorPropertyMapper.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/AccessorPropertyMapper.cs 2011-04-10 18:32:35 UTC (rev 5653) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/Impl/AccessorPropertyMapper.cs 2011-04-10 19:27:37 UTC (rev 5654) @@ -15,16 +15,7 @@ private readonly System.Type declaringType; - private readonly Dictionary<string, IFieldNamingStrategy> fieldNamningStrategies = - new Dictionary<string, IFieldNamingStrategy> - { - {"camelcase", new CamelCaseStrategy()}, - {"camelcase-underscore", new CamelCaseUnderscoreStrategy()}, - {"lowercase", new LowerCaseStrategy()}, - {"lowercase-underscore", new LowerCaseUnderscoreStrategy()}, - {"pascalcase-underscore", new PascalCaseUnderscoreStrategy()}, - {"pascalcase-m-underscore", new PascalCaseMUnderscoreStrategy()}, - }; + private readonly IDictionary<string, IFieldNamingStrategy> fieldNamningStrategies = PropertyToField.DefaultStrategies; private readonly string propertyName; private readonly Action<string> setAccessor; Added: trunk/nhibernate/src/NHibernate/Mapping/ByCode/PropertyToField.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/PropertyToField.cs (rev 0) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/PropertyToField.cs 2011-04-10 19:27:37 UTC (rev 5654) @@ -0,0 +1,32 @@ +using System.Collections.Generic; +using NHibernate.Properties; + +namespace NHibernate.Mapping.ByCode +{ + public class PropertyToField + { + private static readonly Dictionary<string, IFieldNamingStrategy> FieldNamningStrategies = new Dictionary<string, IFieldNamingStrategy> + { + {"camelcase", new CamelCaseStrategy()}, + {"camelcase-underscore", new CamelCaseUnderscoreStrategy()}, + {"lowercase", new LowerCaseStrategy()}, + {"lowercase-underscore", new LowerCaseUnderscoreStrategy()}, + {"pascalcase-underscore", new PascalCaseUnderscoreStrategy()}, + {"pascalcase-m-underscore", new PascalCaseMUnderscoreStrategy()}, + }; + + /// <summary> + /// Dictionary containing the embedded strategies to find a field giving a property name. + /// The key is the "partial-name" of the strategy used in XML mapping. + /// The value is an instance of the strategy. + /// </summary> + public static IDictionary<string, IFieldNamingStrategy> DefaultStrategies + { + get + { + // please leave it as no read-only; the user may need to add his strategies or remove existing if he no want his people use it. + return FieldNamningStrategies; + } + } + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate/Mapping/ByCode/SimpleModelInspector.cs =================================================================== --- trunk/nhibernate/src/NHibernate/Mapping/ByCode/SimpleModelInspector.cs 2011-04-10 18:32:35 UTC (rev 5653) +++ trunk/nhibernate/src/NHibernate/Mapping/ByCode/SimpleModelInspector.cs 2011-04-10 19:27:37 UTC (rev 5654) @@ -22,7 +22,7 @@ private Func<System.Type, bool, bool> isComponent; private Func<MemberInfo, bool, bool> isPersistentId; - private Func<MemberInfo, bool, bool> isPersistentProperty = (m, declared) => declared; + private Func<MemberInfo, bool, bool> isPersistentProperty; private Func<MemberInfo, bool, bool> isVersion = (m, declared) => declared; private Func<MemberInfo, bool, bool> isProperty = (m, declared) => declared; @@ -44,8 +44,53 @@ { isPersistentId = (m, declared) => declared || MatchPoIdPattern(m); isComponent = (t, declared) => declared || MatchComponentPattern(t); + isPersistentProperty = (m, declared) => declared || MatchNoReadOnlyPropertyPattern(m); } + protected bool MatchNoReadOnlyPropertyPattern(MemberInfo subject) + { + var isReadOnlyProperty = IsReadOnlyProperty(subject); + return !isReadOnlyProperty; + } + + protected bool IsReadOnlyProperty(MemberInfo subject) + { + const BindingFlags defaultBinding = BindingFlags.Instance | BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.DeclaredOnly; + + var property = subject as PropertyInfo; + if (property == null) + { + return false; + } + if (CanReadCantWriteInsideType(property) || CanReadCantWriteInBaseType(property)) + { + return !PropertyToField.DefaultStrategies.Values.Any(s => subject.DeclaringType.GetField(s.GetFieldName(property.Name), defaultBinding) != null) || IsAutoproperty(property); + } + return false; + } + + protected bool IsAutoproperty(PropertyInfo property) + { + return property.ReflectedType.GetFields(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance + | BindingFlags.DeclaredOnly).Any(pi => pi.Name == string.Concat("<", property.Name, ">k__BackingField")); + } + + protected bool CanReadCantWriteInsideType(PropertyInfo property) + { + return !property.CanWrite && property.CanRead && property.DeclaringType == property.ReflectedType; + } + + protected bool CanReadCantWriteInBaseType(PropertyInfo property) + { + if (property.DeclaringType == property.ReflectedType) + { + return false; + } + var rfprop = property.DeclaringType.GetProperties(BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance + | BindingFlags.DeclaredOnly).SingleOrDefault(pi => pi.Name == property.Name); + return rfprop != null && !rfprop.CanWrite && rfprop.CanRead; + } + protected bool MatchPoIdPattern(MemberInfo subject) { var name = subject.Name; Modified: trunk/nhibernate/src/NHibernate/NHibernate.csproj =================================================================== --- trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-04-10 18:32:35 UTC (rev 5653) +++ trunk/nhibernate/src/NHibernate/NHibernate.csproj 2011-04-10 19:27:37 UTC (rev 5654) @@ -290,6 +290,7 @@ <Compile Include="Mapping\ByCode\Conformist\JoinedSubclassMapping.cs" /> <Compile Include="Mapping\ByCode\Conformist\SubclassMapping.cs" /> <Compile Include="Mapping\ByCode\Conformist\UnionSubclassMapping.cs" /> + <Compile Include="Mapping\ByCode\PropertyToField.cs" /> <Compile Include="Mapping\ByCode\SimpleModelInspector.cs" /> <Compile Include="Mapping\ByCode\ExplicitlyDeclaredModel.cs" /> <Compile Include="Mapping\ByCode\FakeModelExplicitDeclarationsHolder.cs" /> Added: trunk/nhibernate/src/NHibernate.Test/MappingByCode/MixAutomapping/PropertiesExclusionTests.cs =================================================================== --- trunk/nhibernate/src/NHibernate.Test/MappingByCode/MixAutomapping/PropertiesExclusionTests.cs (rev 0) +++ trunk/nhibernate/src/NHibernate.Test/MappingByCode/MixAutomapping/PropertiesExclusionTests.cs 2011-04-10 19:27:37 UTC (rev 5654) @@ -0,0 +1,103 @@ +using System.Reflection; +using NHibernate.Mapping.ByCode; +using NUnit.Framework; +using SharpTestsEx; + +namespace NHibernate.Test.MappingByCode.MixAutomapping +{ + public class PropertiesExclusionTests + { + public class MyEntity + { + private string noReadOnlyWithField; + private string pizza; + + public string ReadOnly + { + get { return ""; } + } + + public string NoReadOnlyWithField + { + get { return noReadOnlyWithField; } + } + + public string NoReadOnly + { + get { return ""; } + set { } + } + + public string WriteOnly + { + set { } + } + + public string AutoPropWithPrivateSet { get; private set; } + } + + [Test] + public void WhenReadonlyDeclaredThenIsPersistentProperty() + { + var autoinspector = new SimpleModelInspector(); + var mapper = new ModelMapper(autoinspector); + mapper.Class<MyEntity>(map => map.Property(x => x.ReadOnly)); + + var inspector = (IModelInspector)autoinspector; + inspector.IsPersistentProperty(typeof(MyEntity).GetProperty("ReadOnly")).Should().Be.True(); + } + + [Test] + public void WhenReadonlyNotDeclaredThenIsNotPersistentProperty() + { + var autoinspector = new SimpleModelInspector(); + var inspector = (IModelInspector)autoinspector; + + inspector.IsPersistentProperty(typeof(MyEntity).GetProperty("ReadOnly")).Should().Be.False(); + } + + [Test] + public void IncludesReadOnlyWithField() + { + var autoinspector = new SimpleModelInspector(); + var inspector = (IModelInspector)autoinspector; + + PropertyInfo pi = typeof(MyEntity).GetProperty("NoReadOnlyWithField"); + inspector.IsPersistentProperty(pi).Should().Be.True(); + } + + [Test] + public void IncludesNoReadOnly() + { + var autoinspector = new SimpleModelInspector(); + var inspector = (IModelInspector)autoinspector; + + PropertyInfo pi = typeof(MyEntity).GetProperty("NoReadOnly"); + inspector.IsPersistentProperty(pi).Should().Be.True(); + + pi = typeof(MyEntity).GetProperty("WriteOnly"); + inspector.IsPersistentProperty(pi).Should().Be.True(); + } + + [Test] + public void IncludesFields() + { + var autoinspector = new SimpleModelInspector(); + var inspector = (IModelInspector)autoinspector; + + var pi = typeof(MyEntity).GetField("pizza", BindingFlags.Instance | BindingFlags.NonPublic); + inspector.IsPersistentProperty(pi).Should().Be.True(); + } + + [Test] + public void IncludesAutoprop() + { + var autoinspector = new SimpleModelInspector(); + var inspector = (IModelInspector)autoinspector; + + var pi = typeof(MyEntity).GetProperty("AutoPropWithPrivateSet"); + inspector.IsPersistentProperty(pi).Should().Be.True(); + } + + } +} \ No newline at end of file Modified: trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj =================================================================== --- trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-04-10 18:32:35 UTC (rev 5653) +++ trunk/nhibernate/src/NHibernate.Test/NHibernate.Test.csproj 2011-04-10 19:27:37 UTC (rev 5654) @@ -543,6 +543,7 @@ <Compile Include="MappingByCode\MappersTests\SubclassMapperWithJoinPropertiesTest.cs" /> <Compile Include="MappingByCode\MixAutomapping\ComponentsTests.cs" /> <Compile Include="MappingByCode\MixAutomapping\PoidTests.cs" /> + <Compile Include="MappingByCode\MixAutomapping\PropertiesExclusionTests.cs" /> <Compile Include="MappingByCode\ModelExplicitDeclarationsHolderMergeTest.cs" /> <Compile Include="MappingByCode\NatureDemo\Naturalness\Address.cs" /> <Compile Include="MappingByCode\NatureDemo\Naturalness\Animal.cs" /> This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site. |