How to automap a collection of components with Fluent NHibernate?
Asked Answered
M

1

6

All of my entities and value objects implement marker interfaces IEntity and IValueObject. I have set them up to be treated as components like so:

public override bool IsComponent(Type type)
{
    return typeof(IValueObject).IsAssignableFrom(type);
}

public override bool ShouldMap(Type type)
{
    return typeof(IEntity).IsAssignableFrom(type) || typeof(IValueObject).IsAssignableFrom(type);
}

Unfortunately, this does not seem to allow entities that have collections of value objects to be automapped as component collections. For example:

public class MyEntity : IEntity
{
    public IList<MyValueObject> Objects { get; set; }
}

public class MyValueObject : IValueObject
{
    public string Name { get; set; }
    public string Value { get; set; }
}

Is there any way to define a convention such that, any time an IEntity has an IList of a type that implements IValueObject, it gets mapped as if I had specified:

HasMany(x => x.Objects)
    .Component(x => { 
        x.Map(m => m.Name); 
        x.Map(m => m.Value); 
    });

What I don't want to do is have to manually do these overrides for every class and write out each property for the value object again and again.

Macri answered 26/1, 2011 at 22:23 Comment(0)
P
1
  1. Create a new class that inherits from HasManyStep (FluentNHibernate.Automapping.Steps).
  2. Override the ShouldMap() method with something like :

    return base.ShouldMap(member) && IsCollectionOfComponents(member)
    
  3. Add your logic to :

    public void Map(ClassMappingBase classMap, Member member)
    { ... }
    
  4. Replace the default step with your new one :

    public class MyMappingConfiguration : DefaultAutomappingConfiguration
    {
        public override IEnumerable<IAutomappingStep> GetMappingSteps(AutoMapper mapper, IConventionFinder conventionFinder)
        {
            var steps = base.GetMappingSteps(mapper, conventionFinder);
            var finalSteps = steps.Where(c => c.GetType() != typeof(FluentNHibernate.Automapping.Steps.HasManyToManyStep)).ToList();
            var idx = finalSteps.IndexOf(steps.Where(c => c.GetType() == typeof(PropertyStep)).First());
            finalSteps.Insert(idx + 1, new MyCustomHasManyStep(this));
            return finalSteps; 
        }
    }
    

Note : You could also get the original source code of HasManyStep.cs and copy it to your project to introduce your custom logic.

Partner answered 14/11, 2011 at 16:23 Comment(1)
This is an excellent answer that gave me great vision about nhibernate automapping.Companionway

© 2022 - 2024 — McMap. All rights reserved.