Permalink
Browse files

Fixed component in subclass exception. This was happening because the…

… subclass visitor gets all the mappings repeatedly to see which matches, and this doesn't work with our current design. Redesigned components to recreate the mapping on every call to GetMapping (as it should work really!). This needs to be ported to the other mappings.
  • Loading branch information...
1 parent 1115655 commit 3109c1938260f9fe871bfb05c69ca1e533e37cef @jagregory jagregory committed Aug 4, 2009
View
4 src/FluentNHibernate.Testing/FluentInterfaceTests/BaseModelFixture.cs
@@ -40,7 +40,7 @@ public abstract class BaseModelFixture
protected ModelTester<SubclassMap<T>, SubclassMapping> SubclassMapForSubclass<T>()
{
- return new ModelTester<SubclassMap<T>, SubclassMapping>(() => new SubclassMap<T>(), x => (SubclassMapping)x.GetSubclassMapping(new SubclassMapping()));
+ return new ModelTester<SubclassMap<T>, SubclassMapping>(() => new SubclassMap<T>(), x => (SubclassMapping)((IIndeterminateSubclassMappingProvider)x).GetSubclassMapping(new SubclassMapping()));
}
protected ModelTester<JoinedSubClassPart<T>, JoinedSubclassMapping> JoinedSubclass<T>()
@@ -50,7 +50,7 @@ public abstract class BaseModelFixture
protected ModelTester<SubclassMap<T>, JoinedSubclassMapping> SubclassMapForJoinedSubclass<T>()
{
- return new ModelTester<SubclassMap<T>, JoinedSubclassMapping>(() => new SubclassMap<T>(), x => (JoinedSubclassMapping)x.GetSubclassMapping(new JoinedSubclassMapping()));
+ return new ModelTester<SubclassMap<T>, JoinedSubclassMapping>(() => new SubclassMap<T>(), x => (JoinedSubclassMapping)((IIndeterminateSubclassMappingProvider)x).GetSubclassMapping(new JoinedSubclassMapping()));
}
protected ModelTester<ComponentPart<T>, ComponentMapping> Component<T>()
View
40 ...bernate.Testing/FluentInterfaceTests/SubclassMapForSubclassSubPartModelGenerationTests.cs
@@ -1,4 +1,6 @@
+using System;
using System.Linq;
+using FluentNHibernate.Mapping;
using FluentNHibernate.Testing.DomainModel;
using FluentNHibernate.Testing.DomainModel.Mapping;
using NUnit.Framework;
@@ -17,6 +19,44 @@ public void ComponentShouldAddToModelComponentsCollection()
}
[Test]
+ public void ComponentWithPropertiesShouldAddToModelComponentsCollection()
+ {
+ var classMap = new ClassMap<Parent>();
+
+ classMap.Id(x => x.Id);
+
+ var subclassMap = new SubclassMap<Child>();
+
+ subclassMap.Component(x => x.Component, c => c.Map(x => x.Name));
+
+ var model = new PersistenceModel();
+
+ model.Add(classMap);
+ model.Add(subclassMap);
+
+ model.BuildMappings()
+ .First()
+ .Classes.First()
+ .Subclasses.First()
+ .Components.Count().ShouldEqual(1);
+ }
+
+ private class Parent
+ {
+ public int Id { get; set; }
+ }
+
+ private class Child : Parent
+ {
+ public Component Component { get; set; }
+ }
+
+ private class Component
+ {
+ public string Name { get; set; }
+ }
+
+ [Test]
public void DynamicComponentShouldAddToModelComponentsCollection()
{
SubclassMapForSubclass<PropertyTarget>()
View
25 src/FluentNHibernate/Mapping/ComponentPart.cs
@@ -1,27 +1,40 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
+using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;
namespace FluentNHibernate.Mapping
{
public class ComponentPart<T> : ComponentPartBase<T>
{
+ private readonly Type entity;
private readonly AccessStrategyBuilder<ComponentPart<T>> access;
+ private readonly AttributeStore<ComponentMapping> attributes;
public ComponentPart(Type entity, PropertyInfo property)
- : this(new ComponentMapping { ContainingEntityType = entity }, property.Name)
- { }
+ : this(entity, property.Name, new AttributeStore())
+ {}
- private ComponentPart(ComponentMapping mapping, string propertyName)
- : base(mapping, propertyName)
+ private ComponentPart(Type entity, string propertyName, AttributeStore underlyingStore)
+ : base(underlyingStore, propertyName)
{
- access = new AccessStrategyBuilder<ComponentPart<T>>(this, value => mapping.Access = value);
+ attributes = new AttributeStore<ComponentMapping>(underlyingStore);
+ access = new AccessStrategyBuilder<ComponentPart<T>>(this, value => attributes.Set(x => x.Access, value));
+ this.entity = entity;
Insert();
Update();
}
+ protected override IComponentMapping CreateComponentMappingRoot(AttributeStore store)
+ {
+ return new ComponentMapping(store)
+ {
+ ContainingEntityType = entity
+ };
+ }
+
/// <summary>
/// Set the access and naming strategy for this component.
/// </summary>
@@ -65,7 +78,7 @@ public new ComponentPart<T> Update()
public ComponentPart<T> LazyLoad()
{
- mapping.Lazy = nextBool;
+ attributes.Set(x => x.Lazy, nextBool);
nextBool = true;
return this;
}
View
28 src/FluentNHibernate/Mapping/ComponentPartBase.cs
@@ -12,18 +12,22 @@ public abstract class ComponentPartBase<T> : ClasslikeMapBase<T>, IComponentMapp
{
private readonly string propertyName;
private readonly AccessStrategyBuilder<ComponentPartBase<T>> access;
- protected ComponentMappingBase mapping;
protected bool nextBool = true;
+ private readonly AttributeStore<ComponentMappingBase> attributes;
- protected ComponentPartBase(ComponentMappingBase mapping, string propertyName)
+ protected ComponentPartBase(AttributeStore underlyingStore, string propertyName)
{
- this.mapping = mapping;
- access = new AccessStrategyBuilder<ComponentPartBase<T>>(this, value => mapping.Access = value);
+ attributes = new AttributeStore<ComponentMappingBase>(underlyingStore);
+ access = new AccessStrategyBuilder<ComponentPartBase<T>>(this, value => attributes.Set(x => x.Access, value));
this.propertyName = propertyName;
}
+ protected abstract IComponentMapping CreateComponentMappingRoot(AttributeStore store);
+
IComponentMapping IComponentMappingProvider.GetComponentMapping()
{
+ var mapping = CreateComponentMappingRoot(attributes.CloneInner());
+
mapping.Name = propertyName;
foreach (var property in properties)
@@ -62,11 +66,11 @@ public ComponentPartBase<T> ParentReference(Expression<Func<T, object>> exp)
private ComponentPartBase<T> ParentReference(PropertyInfo property)
{
- mapping.Parent = new ParentMapping
+ attributes.Set(x => x.Parent, new ParentMapping
{
Name = property.Name,
ContainingEntityType = typeof(T)
- };
+ });
return this;
}
@@ -82,37 +86,37 @@ public ComponentPartBase<T> Not
public ComponentPartBase<T> ReadOnly()
{
- mapping.Insert = !nextBool;
- mapping.Update = !nextBool;
+ attributes.Set(x => x.Insert, !nextBool);
+ attributes.Set(x => x.Update, !nextBool);
nextBool = true;
return this;
}
public ComponentPartBase<T> Insert()
{
- mapping.Insert = nextBool;
+ attributes.Set(x => x.Insert, nextBool);
nextBool = true;
return this;
}
public ComponentPartBase<T> Update()
{
- mapping.Update = nextBool;
+ attributes.Set(x => x.Update, nextBool);
nextBool = true;
return this;
}
public ComponentPartBase<T> Unique()
{
- mapping.Unique = nextBool;
+ attributes.Set(x => x.Unique, nextBool);
nextBool = true;
return this;
}
public ComponentPartBase<T> OptimisticLock()
{
- mapping.OptimisticLock = nextBool;
+ attributes.Set(x => x.OptimisticLock, nextBool);
nextBool = true;
return this;
}
View
21 src/FluentNHibernate/Mapping/DynamicComponentPart.cs
@@ -1,24 +1,35 @@
using System;
using System.Linq.Expressions;
using System.Reflection;
+using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;
namespace FluentNHibernate.Mapping
{
public class DynamicComponentPart<T> : ComponentPartBase<T>
{
+ private readonly Type entity;
private readonly AccessStrategyBuilder<DynamicComponentPart<T>> access;
+ private readonly AttributeStore<DynamicComponentMapping> attributes;
public DynamicComponentPart(Type entity, PropertyInfo property)
- : this(new DynamicComponentMapping { ContainingEntityType = entity }, property.Name)
+ : this(entity, property.Name, new AttributeStore())
{}
- private DynamicComponentPart(DynamicComponentMapping mapping, string propertyName)
- : base(mapping, propertyName)
+ private DynamicComponentPart(Type entity, string propertyName, AttributeStore underlyingStore)
+ : base(underlyingStore, propertyName)
{
- access = new AccessStrategyBuilder<DynamicComponentPart<T>>(this, value => mapping.Access = value);
+ this.entity = entity;
+ attributes = new AttributeStore<DynamicComponentMapping>(underlyingStore);
+ access = new AccessStrategyBuilder<DynamicComponentPart<T>>(this, value => attributes.Set(x => x.Access, value));
+ }
- this.mapping = mapping;
+ protected override IComponentMapping CreateComponentMappingRoot(AttributeStore store)
+ {
+ return new DynamicComponentMapping(store)
+ {
+ ContainingEntityType = entity
+ };
}
/// <summary>
View
2 src/FluentNHibernate/Mapping/SubclassMap.cs
@@ -25,7 +25,7 @@ public SubclassMap<T> Not
}
}
- public ISubclassMapping GetSubclassMapping(ISubclassMapping mapping)
+ ISubclassMapping IIndeterminateSubclassMappingProvider.GetSubclassMapping(ISubclassMapping mapping)
{
GenerateNestedSubclasses(mapping);
View
2 src/FluentNHibernate/MappingModel/ClassBased/ComponentMapping.cs
@@ -11,7 +11,7 @@ public ComponentMapping()
: this(new AttributeStore())
{}
- private ComponentMapping(AttributeStore store)
+ public ComponentMapping(AttributeStore store)
: base(store)
{
attributes = new AttributeStore<ComponentMapping>(store);
View
2 src/FluentNHibernate/MappingModel/ClassBased/DynamicComponentMapping.cs
@@ -11,7 +11,7 @@ public DynamicComponentMapping()
: this(new AttributeStore())
{ }
- private DynamicComponentMapping(AttributeStore store)
+ public DynamicComponentMapping(AttributeStore store)
: base(store)
{
attributes = new AttributeStore<DynamicComponentMapping>(store);
View
8 src/FluentNHibernate/MappingModel/ClassBased/IComponentMapping.cs
@@ -13,7 +13,7 @@ public interface IComponentMapping
bool Update { get; set; }
string Access { get; set; }
Type ContainingEntityType { get; }
- string Name { get; }
+ string Name { get; set; }
PropertyInfo PropertyInfo { get; }
Type Type { get; }
bool Lazy { get; }
@@ -25,5 +25,11 @@ public interface IComponentMapping
IEnumerable<IComponentMapping> Components { get; }
IEnumerable<OneToOneMapping> OneToOnes { get; }
IEnumerable<AnyMapping> Anys { get; }
+ void AddProperty(PropertyMapping mapping);
+ void AddComponent(IComponentMapping mapping);
+ void AddOneToOne(OneToOneMapping mapping);
+ void AddCollection(ICollectionMapping mapping);
+ void AddReference(ManyToOneMapping mapping);
+ void AddAny(AnyMapping mapping);
}
}
View
1 src/FluentNHibernate/MappingModel/ClassBased/ISubclassMapping.cs
@@ -9,6 +9,7 @@ public interface ISubclassMapping : IMappingBase
string Name { get; set; }
Type Type { get; }
IEnumerable<ISubclassMapping> Subclasses { get; }
+ IEnumerable<IComponentMapping> Components { get; }
void OverrideAttributes(AttributeStore store);
void AddProperty(PropertyMapping mapping);
void AddComponent(IComponentMapping mapping);

0 comments on commit 3109c19

Please sign in to comment.