Fluent NHibernate Automapping with abstract base class
Asked Answered
J

1

7

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?

Jegar answered 9/5, 2011 at 11:13 Comment(0)
I
4

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.

Irinairis answered 11/7, 2012 at 14:39 Comment(3)
wow, didn't expect an answer anymore. I cannot check the answer since i am no longer working for the company where i ran into this issue. (don't even have the code anymore). Still thumbs up for answering this one. Maybe it will help somebody else.Jegar
I haven't heard anything if this answer works but from reading it I;d say it will work. Thanks for the advice.Jegar
Just FYI from 5 years down the road: your fix worked perfectly.Noli

© 2022 - 2024 — McMap. All rights reserved.