Skip to content

Commit

Permalink
Introduced new way to configure the automapper.
Browse files Browse the repository at this point in the history
The automapper can (and should) now be configured by supplying a
configuration instance -- an implementation of IAutomappingConfiguration
-- which specifies how the automapper should behave when mapping the
domain.

All configuration options from the Setup action have been migrated,
along with the Where method.

The Setup-based usage is still available (although depreciated), but you
can't mix-and-match the types; if a configuration instance is supplied
the Setup and Where methods will throw.

The automapper has also been modified to act on all members of a class,
ra than just properties. The default is still to use properties, but the
ShouldMap(Member) method can be overridden to use fields or any
combination.
  • Loading branch information
jagregory committed Apr 30, 2010
1 parent bb2d939 commit 9ccf861
Show file tree
Hide file tree
Showing 68 changed files with 2,532 additions and 1,685 deletions.
@@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using FluentNHibernate.Automapping;
using FluentNHibernate.Specs.Automapping.Fixtures;
using Machine.Specifications;

namespace FluentNHibernate.Specs.Automapping
{
// just verify that the obsolete methods still work until we bin them entirely

public class when_using_automap_obsolete_where_method_for_assembly_of : AutoMapObsoleteSpec
{
Because of = () =>
AutoMap.AssemblyOf<EntityUsingPrivateFields>(where_clause)
.BuildMappings();

It should_use_the_where_clause_provided = () =>
was_called.ShouldBeTrue();
}

public class when_using_automap_obsolete_where_method_for_an_assembly : AutoMapObsoleteSpec
{
Because of = () =>
AutoMap.Assembly(typeof(EntityUsingPrivateFields).Assembly, where_clause)
.BuildMappings();

It should_use_the_where_clause_provided = () =>
was_called.ShouldBeTrue();
}

public class when_using_automap_obsolete_where_method_for_a_source : AutoMapObsoleteSpec
{
Because of = () =>
AutoMap.Source(new StubTypeSource(typeof(EntityUsingPrivateFields)), where_clause)
.BuildMappings();

It should_use_the_where_clause_provided = () =>
was_called.ShouldBeTrue();
}

public abstract class AutoMapObsoleteSpec
{
protected static Func<Type, bool> where_clause = x => !(was_called = true);
protected static bool was_called;
}
}
@@ -0,0 +1,33 @@
using System.Xml;
using FluentNHibernate.Automapping;
using FluentNHibernate.Conventions;
using FluentNHibernate.Conventions.Instances;
using FluentNHibernate.Specs.Automapping.Fixtures;
using Machine.Specifications;

namespace FluentNHibernate.Specs.Automapping
{
public class when_the_automapper_maps_with_a_property_convention
{
Establish context = () =>
mapper = AutoMap.Source(new StubTypeSource(typeof(Entity)))
.Conventions.Add<XXAppenderPropertyConvention>();

Because of = () =>
xml = mapper.BuildMappingFor<Entity>().ToXml();

It should_apply_the_convention_to_any_properties = () =>
xml.Element("class/property[@name='One']/column").HasAttribute("name", "OneXX");

static AutoPersistenceModel mapper;
static XmlDocument xml;

class XXAppenderPropertyConvention : IPropertyConvention
{
public void Apply(IPropertyInstance instance)
{
instance.Column(instance.Name + "XX");
}
}
}
}
@@ -0,0 +1,58 @@
using System;
using System.Xml;
using FluentNHibernate.Automapping;
using FluentNHibernate.Cfg;
using FluentNHibernate.Cfg.Db;
using FluentNHibernate.Specs.Automapping.Fixtures;
using Machine.Specifications;

namespace FluentNHibernate.Specs.Automapping
{
public class when_the_automapper_is_told_to_map_a_single_type
{
Because of = () =>
xml = AutoMap.Source(new StubTypeSource(typeof(Entity)))
.BuildMappingFor<Entity>()
.ToXml();

It should_only_return_one_class_in_the_xml = () =>
{
xml.Element("class").ShouldExist();
xml.Element("class[2]").ShouldNotExist();
};

It should_map_the_id = () =>
xml.Element("class/id").ShouldExist();

It should_map_properties = () =>
xml.Element("class/property[@name='One']").ShouldExist();

It should_map_enum_properties = () =>
xml.Element("class/property[@name='Enum']").ShouldExist();

It should_map_references = () =>
xml.Element("class/many-to-one[@name='Parent']").ShouldExist();

It should_map_collections = () =>
xml.Element("class/bag[@name='Children']").ShouldExist();

static XmlDocument xml;
}

public class when_the_automapper_is_ran_to_completion
{
Establish context = () =>
setup = Fluently.Configure()
.Database(SQLiteConfiguration.Standard.InMemory)
.Mappings(x => x.AutoMappings.Add(AutoMap.Source(new StubTypeSource(typeof(Entity)))));

Because of = () =>
ex = Catch.Exception(() => setup.BuildConfiguration());

It should_generate_xml_that_is_accepted_by_the_nhibernate_schema_validation = () =>
ex.ShouldBeNull();

static FluentConfiguration setup;
static Exception ex;
}
}
@@ -1,5 +1,7 @@
using System.Linq;
using System;
using System.Linq;
using FluentNHibernate.Automapping;
using FluentNHibernate.Automapping.Steps;
using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;
using FluentNHibernate.MappingModel.Collections;
Expand All @@ -11,7 +13,7 @@ namespace FluentNHibernate.Specs.Automapping
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_strings : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfStrings);
maps_property = step.ShouldMap(FakeMembers.IListOfStrings);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -22,7 +24,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_strings : Auto
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_ints : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfInts);
maps_property = step.ShouldMap(FakeMembers.IListOfInts);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -33,7 +35,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_ints : AutoMap
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_doubles : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfDoubles);
maps_property = step.ShouldMap(FakeMembers.IListOfDoubles);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -44,7 +46,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_doubles : Auto
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_shorts : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfShorts);
maps_property = step.ShouldMap(FakeMembers.IListOfShorts);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -55,7 +57,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_shorts : AutoM
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_longs : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfLongs);
maps_property = step.ShouldMap(FakeMembers.IListOfLongs);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -66,7 +68,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_longs : AutoMa
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_floats : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfFloats);
maps_property = step.ShouldMap(FakeMembers.IListOfFloats);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -77,7 +79,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_floats : AutoM
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_bools : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfBools);
maps_property = step.ShouldMap(FakeMembers.IListOfBools);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -88,7 +90,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_bools : AutoMa
public class when_the_automapper_is_asked_if_it_can_map_a_list_of_DateTimes : AutoMapOneToManyVisitSpec
{
Because of = () =>
maps_property = step.MapsProperty(FakeMembers.IListOfDateTimes);
maps_property = step.ShouldMap(FakeMembers.IListOfDateTimes);

It should_accept_the_property = () =>
maps_property.ShouldBeTrue();
Expand All @@ -99,7 +101,7 @@ public class when_the_automapper_is_asked_if_it_can_map_a_list_of_DateTimes : Au
public class when_the_automapper_is_told_to_map_a_list_of_simple_types_with_a_custom_column_defined : AutoMapOneToManySpec
{
Establish context = () =>
expressions.SimpleTypeCollectionValueColumn = t => "custom_column";
cfg.FixedSimpleTypeCollectionValueColumn = "custom_column";

Because of = () =>
step.Map(container, FakeMembers.IListOfStrings);
Expand Down Expand Up @@ -157,28 +159,38 @@ public abstract class AutoMapOneToManySpec
{
Establish context = () =>
{
expressions = new AutoMappingExpressions();
step = new AutoMapOneToMany(expressions);
cfg = new TestConfiguration();
step = new HasManyStep(cfg);
container = new ClassMapping
{
Type = FakeMembers.Type
};
};

protected static AutoMapOneToMany step;
protected static HasManyStep step;
protected static ClassMapping container;
protected static AutoMappingExpressions expressions;
protected static TestConfiguration cfg;

protected class TestConfiguration : DefaultAutomappingConfiguration
{
public override string SimpleTypeCollectionValueColumn(Member member)
{
return FixedSimpleTypeCollectionValueColumn ?? base.SimpleTypeCollectionValueColumn(member);
}

public string FixedSimpleTypeCollectionValueColumn { get; set; }
}
}

public abstract class AutoMapOneToManyVisitSpec
{
Establish context = () =>
{
expressions = new AutoMappingExpressions();
step = new AutoSimpleTypeCollection(expressions);
cfg = new DefaultAutomappingConfiguration();
step = new SimpleTypeCollectionStep(cfg);
};

protected static AutoSimpleTypeCollection step;
protected static AutoMappingExpressions expressions;
protected static SimpleTypeCollectionStep step;
protected static IAutomappingConfiguration cfg;
}
}
@@ -0,0 +1,113 @@
using System;
using System.Linq;
using System.Xml;
using FluentNHibernate.Automapping;
using FluentNHibernate.MappingModel;
using FluentNHibernate.MappingModel.ClassBased;
using FluentNHibernate.MappingModel.Output;
using Machine.Specifications;

namespace FluentNHibernate.Specs.Automapping.Fixtures
{
public static class AutomappingSpecExtensions
{
public static ClassMapping BuildMappingFor<T>(this AutoPersistenceModel model)
{
return model.BuildMappings()
.SelectMany(x => x.Classes)
.FirstOrDefault(x => x.Type == typeof(T));
}

public static XmlDocument ToXml(this ClassMapping mapping)
{
var hbm = new HibernateMapping();

hbm.AddClass(mapping);

return new MappingXmlSerializer()
.Serialize(hbm);
}
}

public static class XmlTestExtensions
{
public static XmlElementTester Element(this XmlDocument doc, string path)
{
return new XmlElementTester(doc, path);
}

public class XmlElementTester
{
readonly XmlDocument doc;
string currentPath;
XmlElement currentElement;

public XmlElementTester(XmlDocument doc, string path)
{
currentElement = (XmlElement)doc.DocumentElement.SelectSingleNode(path);
this.doc = doc;
currentPath = path;
}

public XmlElementTester ShouldExist()
{
if (currentElement == null)
throw new SpecificationException(string.Format("Should exist at {0} but does not.", currentPath));

return this;
}

public XmlElementTester ShouldNotExist()
{
if (currentElement != null)
throw new SpecificationException(string.Format("Should not exist at {0} but does.", currentPath));

return this;
}

public XmlElementTester HasAttribute(string name)
{
if (!currentElement.HasAttribute(name))
throw new SpecificationException(string.Format("Should have attribute named {0} at {1} but does not.", name, currentPath));

return this;
}

public XmlElementTester HasAttribute(string name, string value)
{
ShouldExist();
HasAttribute(name);

var actual = currentElement.GetAttribute(name);

if (!actual.Equals(value))
throw new SpecificationException(string.Format("Should have attribute named {0} at {1} with value of {2} but was {3}", name, currentPath, value, actual));

return this;
}

public XmlElementTester HasAttribute(string name, Func<string, bool> predicate)
{
ShouldExist();
HasAttribute(name);

var actual = currentElement.GetAttribute(name);

if (!predicate(actual))
throw new SpecificationException(string.Format("Should have attribute named {0} at {1} with value matching predicate but does not.", name, currentPath));

return this;
}

public XmlElementTester DoesntHaveAttribute(string name)
{
ShouldExist();

if (currentElement.HasAttribute(name))
throw new SpecificationException(string.Format("Should not have attribute named {0} at {1} but does.", name, currentPath));

return this;
}
}
}
}

0 comments on commit 9ccf861

Please sign in to comment.