C # Automapper How to enable the use of a property from customresolver

I use the following mapping to map a data object to a viewmodel.

ObjectMapper.cs

public static class ObjectMapper { public static void Configure() { Mapper.CreateMap<User, UserViewModel>() .ForMember(dest => dest.Title, opt => opt.ResolveUsing<TitleValueResolver>()) .ForMember(dest => dest.Name, opt => opt.ResolveUsing<NameValueResolver >()) .ForMember(dest => dest.ShortName, opt => opt.ResolveUsing<ShortNameValueResolver >()); } } 

Parser

 public class Parser{ public string GetTitle(string title){ /* add some logic */ return title; } public string GetName(string title){ /* add some logic */ return name; } public string GetShortName(string title){ /* add some logic */ return shortname; } } 

AutoMapperCustomResolvers.cs

 public class TitleValueResolver : ValueResolver<User, string> { private readonly BaseValueResolver _baseResolver; public TitleValueResolver() { _baseResolver = new BaseValueResolver(); } protected override string ResolveCore(Usersource) { return _baseResolver.Parser.GetTitle(source.TITLE); } } public class NameValueResolver : ValueResolver<User, string> { private readonly BaseValueResolver _baseResolver; public NameValueResolver() { _baseResolver = new BaseValueResolver(); } protected override string ResolveCore(Usersource) { return _baseResolver.Parser.GetName(source.TITLE); } } public class ShortNameValueResolver : ValueResolver<User, string> { private readonly BaseValueResolver _baseResolver; public ShortNameValueResolver() { _baseResolver = new BaseValueResolver(); } protected override string ResolveCore(Usersource) { return _baseResolver.Parser.GetShortName(source.TITLE); } } 

I use the above code to add logic to the destination property using separate custom value variables. Not sure if this is the right approach.

i) Is there a better way to achieve this?

ii) And how to use unity for resolution in case I want to put some dependency in the constructor of custom resolvers?

thanks

+5
source share
1 answer

As I understand your question, you want to use ValueResolver , which resolves several source properties into an intermediate data object, which is used to resolve several target properties. As an example, I assume the following types of sources, target, intermediate, and permissive:

 // source class User { public string UserTitle { get; set; } } // target class UserViewModel { public string VM_Title { get; set; } public string VM_OtherValue { get; set; } } // intermediate from ValueResolver class UserTitleParserResult { public string TransferTitle { get; set; } } class TypeValueResolver : ValueResolver<User, UserTitleParserResult> { protected override UserTitleParserResult ResolveCore(User source) { return new UserTitleParserResult { TransferTitle = source.UserTitle }; } } 

To use opt.ResolveUsing<TypeValueResolver>() , the target property is required. This means that you can set the mapping in which the corresponding target property is available.

So, for now, let's wrap the result in the appropriate container type:

 class Container<TType> { public TType Value { get; set; } } 

And create a mapping

 Mapper.CreateMap<User, Container<UserViewModel>>() .ForMember(d => d.Value, c => c.ResolveUsing<TypeValueResolver>()); 

And another display

 Mapper.CreateMap<UserTitleParserResult, UserViewModel>() .ForMember(d => d.VM_Title, c => c.MapFrom(s => s.TransferTitle)) .ForMember(d => d.VM_OtherValue, c => c.Ignore()); 

And another display

 Mapper.CreateMap<User, UserViewModel>() .BeforeMap((s, d) => { Mapper.Map<User, Container<UserViewModel>>(s, new Container<UserViewModel> { Value = d }); }) .ForAllMembers(c => c.Ignore()); // establish more rules for properties... 

The latter mapping is a bit special, as it relies on a nested mapping to update the receiver with values ​​from the source through separately configured matching rules. You can have several different carry mappings for different properties by adding the appropriate intermediate mappings and calls to the BeforeMap actual display type. Properties that are handled in other mappings must be ignored because AutoMapper is unaware of the mapping in BeforeMap

A small usage example:

 var user = new User() { UserTitle = "User 1" }; // create by mapping UserViewModel vm1 = Mapper.Map<UserViewModel>(user); UserViewModel vm2 = new UserViewModel() { VM_Title = "Title 2", VM_OtherValue = "Value 2" }; // map source properties into existing target Mapper.Map(user, vm2); 

I don’t know if this will help you. There may be better ways if you rephrase your question to describe your original problem, rather than what you think is the solution.

0
source

All Articles