I am trying out the FluentNHibernate AutoPersistenceModel for the first time. It was very simple to get a basic example working but I am having a problem making it fit with how I work. I normally work to interfaces so that my entities all implement an interface and reference all related entities by their interface, not their concrete type. Given the following classes:
public Interface IFoo { }
public Interface IBar { IFoo Foo { get; set; } }
public Class Foo : IFoo { }
public Class Bar : IBar
{
public IFoo Foo { get; set; }
}
I would have the following mapping:
public class BarMapping : ClassMap<Bar>
{
public AnswerMapping()
{
References<Foo>( x => x.Foo ).Column( "FooId" ).Cascade.None();
}
}
How would I achieve the same with the AutoPersistenceModel? I have had a brief look at Conventions and the ReferenceConvention builder but without any documentation or examples I have been floundering.
EDIT
I have now turned this along with my other SO post on collection mapping to interfaces into a blog post:
http://bronumski.blogspot.com/2011/01/making-fluent-nhibernate-automapper.html
After a little digging around I have come up with a solution. There is an IReferenceConvention interface which I have seen used in other examples but don't cover this scenario. By implementing the interface and doing a custom convention I have been able to achieve the same thing with the AutoPersistenceModel that I was with ClassMap.
public class ReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
Type instanceType = instance.Class.GetUnderlyingSystemType();
if (instanceType == typeof(IFoo))
{
instance.CustomClass<Foo>();
}
instance.Cascade.All();
}
}
A more generic approach might be:
public class ReferenceConvention : IReferenceConvention
{
public void Apply(IManyToOneInstance instance)
{
Type instanceType = instance.Class.GetUnderlyingSystemType();
if (instanceType.IsInterface)
{
// Assuming that the type starts with an I get the name of the concrete class
string className = instanceType.Name.Substring( 1 );
instance.CustomClass(instanceType.Assembly.GetType(
instanceType.FullName.Replace( instanceType.Name, className )));
}
instance.Cascade.All();
}
}
There is also a ReferenceConventionBuilder which I have not looked at yet but this could be a cleaner solution.