views:

172

answers:

4

I'm trying to map int IdPost on DTO to Post object on Blog object, based on a rule.

I would like to achieve this: BlogDTO.IdPost => Blog.Post

Post would be loaded by NHibernate: Session.Load(IdPost)

How can I achieve this with AutoMapper?

A: 

If you have a public setter on Id property in Post class

public class Post 
{
      public int Id {get;set;}
}

public class SomeDto
{
      public int PostId {get;set;}
}

then I believe all you need to do is

Mapper.CreateMap<SomeDto,Post>();

or if your properties names don't match this convention you could use

Mapper.CreateMap<SomeDto,Post>()
     .ForMember(dst=> dst.Id, opt=> opt.MapFrom(src => src.IdPost));

However I don't think that mapping a dto directly to a domain object is a good idea.

miensol
A: 

You could define AfterMap action to load entities using NHibernate in your mapping definition. I'm using something like this for simmilar purpose:

        mapperConfiguration.CreateMap<DealerDTO, Model.Entities.Dealer.Dealer>()
            .AfterMap((src, dst) =>
                {
                    if (src.DepartmentId > 0)
                        dst.Department = nhContext.CurrentSession.Load<CompanyDepartment>(src.DepartmentId);
                    if (src.RankId > 0)
                        dst.Rank = nhContext.CurrentSession.Load<DealerRank>(src.RankId);
                    if (src.RegionId > 0)
                        dst.Region = nhContext.CurrentSession.Load<Region>(src.RegionId);
                });
Buthrakaur
this is very labor intensive. You need to make framework do all of the work for you.
epitka
A: 
  1. Create a new Id2EntityConverter

    public class Id2EntityConverter : ITypeConverter where TEntity : EntityBase { public Id2EntityConverter() { Repository = ObjectFactory.GetInstance>(); }

        private IRepository<TEntity> Repository { get; set; }
    
    
    
    public TEntity ConvertToEntity(int id)
    {
        var toReturn = Repository.Get(id);
        return toReturn;
    }
    
    
    #region Implementation of ITypeConverter&lt;int,TEntity&gt;
    
    
    public TEntity Convert(ResolutionContext context)
    {
        return ConvertToEntity((int)context.SourceValue);
    }
    
    
    #endregion
    
    }
  2. Configure AM to auto create maps for each type

    public class AutoMapperGlobalConfiguration : IGlobalConfiguration { private AutoMapper.IConfiguration _configuration;

        public AutoMapperGlobalConfiguration(IConfiguration configuration)
        {
            _configuration = configuration;
        }
    
    
    
    public void Configure()
    {
        //add all defined profiles
        var query = this.GetType().Assembly.GetExportedTypes()
            .Where(x =&gt; x.CanBeCastTo(typeof(AutoMapper.Profile)));
    
    
        _configuration.RecognizePostfixes("Id");
    
    
        foreach (Type type in query)
        {
            _configuration.AddProfile(ObjectFactory.GetInstance(type).As&lt;Profile&gt;());
        }
    
    
        //create maps for all Id2Entity converters
        MapAllEntities(_configuration);
    
    
       Mapper.AssertConfigurationIsValid();
    }
    
    
    private static void MapAllEntities(IProfileExpression configuration)
    {
        //get all types from the my assembly and create maps that
        //convert int -&gt; instance of the type using Id2EntityConverter
        var openType = typeof(Id2EntityConverter&lt;&gt;);
        var idType = typeof(int);
        var persistentEntties = typeof(MYTYPE_FROM_MY_ASSEMBLY).Assembly.GetTypes()
           .Where(t =&gt; typeof(EntityBase).IsAssignableFrom(t))
           .Select(t =&gt; new
           {
               EntityType = t,
               ConverterType = openType.MakeGenericType(t)
           });
        foreach (var e in persistentEntties)
        {
            var map = configuration.CreateMap(idType, e.EntityType);
            map.ConvertUsing(e.ConverterType);
        }
    }
    
    }

Pay attention to MapAllEntities method. That one will scan all types and create maps on the fly from integer to any type that is of EntityBase (which in our case is any persistent type). RecognizePostfix("Id") in your case might be replace with RecognizePrefix("Id")

epitka
if you need I can send you all pieces that you need to set this up via email
epitka
A: 

you can do this easily with the ValueInjecter

it would be something like this:

//first you need to create a ValueInjection for your scenario
      public class IntToPost : LoopValueInjection<int, Post>
        {
            protected override Post SetValue(int sourcePropertyValue)
            {
                return Session.Load(sourcePropertyValue);
            }
        }

// and use it like this
post.InjectFrom(new IntToPost().SourcePrefix("Id"), postDto);

also if you always have the prefix Id than you could set it in the constructor of the IntToPost and use it like this:

post.InjectFrom<IntToPost>(postDto);
Omu