Implementing AutoMapper for Model Mapping in Prism Applications
Reflection-based model mapping in Prism struggles with type conversion between identical field names in Model and DTO classes, often requiring complex workarounds.
AutoMapper simplifies this process, though its integration with Prism is less common compared to ASP.NET Core applications. The implementation follows dependency injection patterns for AutoMapper instantiation.
Model Definitions
public class StudentModel
{
public int Identifier { get; set; }
public string FullName { get; set; }
public bool? IsMale { get; set; }
public DateTime BirthDate { get; set; }
}
public class StudentDataTransfer
{
public int Identifier { get; set; }
public string FullName { get; set; }
public string BirthDate { get; set; }
}
Reflection-Based Mapping
Reflection mapping iterates through source properties and assigns values to matching destination properties.
public static StudentDataTransfer MapUsingReflection(StudentModel source)
{
var result = new StudentDataTransfer();
var targetType = typeof(StudentDataTransfer);
var sourceType = typeof(StudentModel);
var sourceProperties = sourceType.GetProperties();
foreach (var prop in sourceProperties)
{
var targetProperty = targetType.GetProperty(prop.Name);
targetProperty?.SetValue(result, prop.GetValue(source));
}
return result;
}
AutoMapper Implementation
AutoMapper requires MapperConfiguration setup to obtain IMapper instances for object transformation.
- Create Mapping Profile
public class StudentMappingProfile : Profile
{
public StudentMappingProfile()
{
CreateMap<StudentModel, StudentDataTransfer>()
.ForMember(
dest => dest.BirthDate,
opt => opt.MapFrom(src => $"{src.BirthDate:yyyy-MM-dd HH:mm:ss}")
);
}
}
- Maper Configuration Wrapper
Encapsulate MapperConfiguration to provide IMapper instances.
public interface IMapperFactory
{
IMapper CreateMapper();
}
public class MapperFactory : IMapperFactory
{
private readonly MapperConfiguration _config;
public MapperFactory(IContainerProvider containerProvider)
{
_config = new MapperConfiguration(cfg =>
{
cfg.ConstructServicesUsing(containerProvider.Resolve);
cfg.AddMaps(Assembly.GetExecutingAssembly());
});
}
public IMapper CreateMapper()
{
return _config.CreateMapper();
}
}
- Dependency Injection Registration
Register mapping services with the IoC container.
protected override void RegisterTypes(IContainerRegistry container)
{
container.RegisterSingleton<IMapperFactory, MapperFactory>();
container.Register<IMapper>(CreateMapperInstance);
}
private IMapper CreateMapperInstance(IContainerProvider provider)
{
var factory = provider.Resolve<IMapperFactory>();
return factory.CreateMapper();
}
- AutoMapper Usage
Utilize IMapper through dependency injection for model transformations.
public class MainViewModel : BindableBase
{
private readonly IMapper _objectMapper;
public MainViewModel(IMapper mapper)
{
_objectMapper = mapper;
}
}
Single Object Mapping
private StudentDataTransfer ConvertStudent(StudentModel student)
{
return _objectMapper.Map<StudentDataTransfer>(student);
}
Collection Mapping
var convertedStudents = _objectMapper.Map<List<StudentModel>, List<StudentDataTransfer>>(students);