Force all types derived from class to be mapped as properties when auto-mapping

34 views
Skip to first unread message

Paul Cox

unread,
Aug 6, 2011, 10:13:48 AM8/6/11
to fluent-n...@googlegroups.com
I have moved from specifying fluent configurations using ClassMaps to using auto-mapping but I am having a problem with property conventions.

The problem is that the auto-mapper is mapping all class-based properties as many-to-one references by default. This is great in most cases but I want all properties derived from Enumeration to be mapped as properties instead to take advantage of the following convention.

public class EnumerationTypeConvention : IPropertyConvention, IPropertyConventionAcceptance
    {
        private static readonly Type OpenType = typeof(EnumerationType<>);

        public void Apply(IPropertyInstance instance)
        {
            Type closedType = OpenType.MakeGenericType(instance.Property.PropertyType);

            instance.CustomType(closedType);
        }

        public void Accept(IAcceptanceCriteria<IPropertyInspector> criteria)
        {
            criteria.Expect(x => typeof(Enumeration).IsAssignableFrom(x.Property.PropertyType));
        }
    }

Currently I am having to override every Enumeration-derived property by hand using an AutoMappingOverride class, which is not the end of the world, but it would be great if there was a way to do this automatically.

Paul Cox

unread,
Aug 8, 2011, 5:06:10 PM8/8/11
to fluent-n...@googlegroups.com
I had a look through the Fluent NHibernate code and it seems like you need to replace the PropertyStep with a custom one.
    public class AutomappingConfiguration : DefaultAutomappingConfiguration
    {
        public override IEnumerable<IAutomappingStep> GetMappingSteps(AutoMapper mapper, IConventionFinder conventionFinder)
        {
            return new IAutomappingStep[]
            {
                new IdentityStep(this),
                new VersionStep(this),
                new ComponentStep(this, mapper),
                new CustomPropertyStep(conventionFinder, this),
                new HasManyToManyStep(this),
                new ReferenceStep(this),
                new HasManyStep(this)
            };
        }
    }
    public class CustomPropertyStep : IAutomappingStep
    {
        private readonly IAutomappingStep _defaultPropertyStep;

        public CustomPropertyStep(IConventionFinder conventionFinder, IAutomappingConfiguration cfg)
        {
            _defaultPropertyStep = new PropertyStep(conventionFinder, cfg);
        }

        public bool ShouldMap(Member member)
        {
            return _defaultPropertyStep.ShouldMap(member) || typeof(Enumeration).IsAssignableFrom(member.PropertyType);
        }

        public void Map(ClassMappingBase classMap, Member member)
        {
            _defaultPropertyStep.Map(classMap, member);
        }
    }

Eric

unread,
Aug 8, 2011, 7:19:10 PM8/8/11
to Fluent NHibernate
Paul,

I have an Enumeration class (similar to the Java Enumeration) as well
in my current code base and I used a generic IUserType as follows:

[Serializable]
public class EnumerationUserType<T> : IUserType
where T : Enumeration
{
...
}

And then add the usertype convention in the
AutoPersistanceModelGenerator as
follows: .Conventions.Add<EnumerationUserTypeConvention<DeviceTypes>>()

I am thinking in a future iteration I will just make it search my
domain assembly for all types of Enumeration so I don't have to add
the convention for each model.

Eric

Eric

unread,
Aug 8, 2011, 7:23:09 PM8/8/11
to Fluent NHibernate
I realized I missed the actual convention:

namespace Foo {
public class EnumerationUserTypeConvention<TEnumeration>
: UserTypeConvention<EnumerationUserType<TEnumeration>>
where TEnumeration : Enumeration { }
}
Reply all
Reply to author
Forward
0 new messages