Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Fluent NHibernate Automapping with abstract base class

Given the classes below:

public class Address : Place
{
    public virtual string Street { get; set; }
    public virtual int Number  { get; set; }


    public override string WhereAmI
    {
        get { string.Format("{0} {1}", Street , Number); }
    }
}
public abstract class Place : DomainEntity
{
    public abstract string WhereAmI { get; }
}

When I use this mapping:

var autoMap = AutoMap.AssemblyOf<Party>()
            .Override<Place>(map => map.IgnoreProperty(p => p.WhereAmI))
            .Override<Address>(map => map.IgnoreProperty(p => p.WhereAmI))
            .Where(type => type.Namespace != null && type.Namespace.Contains("Models"));

I still get the error: Could not find a setter for property 'WhereAmI' in class 'Address'

Things I did:

  • When i remove the property from the base class "Address" it works.
  • When i use .OverrideAll(map => map.IgnoreProperty("WhereAmI")) But I don't want it to be global because in another class i might use the same property name where I DO want to include this Property

Is there any way to get this to work other then to use an Interface?

like image 424
amaters Avatar asked May 09 '11 11:05

amaters


1 Answers

I tried tracking down in the FluentNHibernate code exactly why the IgnoreProperty seems to break down when the property being ignored is coming from a base class, but ran out of time. It seems to work fine if the get-only property is not coming from a base class.

Anyway, the solution to your situation seems to be to create a custom IAutomappingConfiguration by inheriting from DefaultAutomappingConfiguration. See this stack overflow answer: How can I create a Fluent NHibernate Convention that ignores properties that don't have setters.

Here's the custom automapping configuration that I used successfully to automap the example entity you provided:

protected class CustomConfiguration : DefaultAutomappingConfiguration
{
    public override bool ShouldMap (Member member)
    {
        if (member.IsProperty && member.IsPublic && !member.CanWrite)
        {
            return false;
        }

        return base.ShouldMap(member);
    }

    public override bool ShouldMap(Type type)
    {
        return type.Namespace != null && type.Namespace.Contains("Models");
    }
}

And then its use:

var autoMap = AutoMap
            .AssemblyOf<DomainEntity>(new CustomConfiguration());

Note that the Where clause in your example had to move into the custom configuration class as its not allowed to be chained if you are using a custom configuration instance.

like image 141
NFrank Avatar answered Nov 13 '22 16:11

NFrank