Why does AutoMapper have an IValueFormatter when it has a seemingly much more powerful ValueResolver?
It looks like an IValueFormatter
takes a value of type object
and returns a value of type string
, whil开发者_如何学JAVAe a ValueResolver<TSource, TDestination>
takes a value of any type and returns a value of any type. So, it's more flexible. There is also the matter that, with a ValueResolver
, you never need to cast the source to a particular type--you define it explicitly in your class definition.
Given this, why use IValueFormatter
? Does it do anything that can't be done with ValueResolver
? Am I misunderstanding how it works?
The big difference is that formatters can be applied at the member, profile, type and global level. So you can do something like "ForSourceType.AddFormatter() in a profile, and now blammo! All your decimals now show up as money. Resolvers are strictly for custom member mapping.
Okay, I think I've figured this out:
With an
IValueFormatter
, the input to theFormatValue()
method is the actual value. (Okay, technically, it's aResolutionContext
object that lets you get at the value using theSourceValue
property, but you get the idea).With a
ValueResolver
, the input to theResolveCore()
method is the entire source (not just the source value).
So, if you want to do some kind of conversion between a source value and a destination value, an IValueFormatter
will only work if the destination type is a string
, and a ValueResolver
will only work if the ResolveCore()
method "knows" which property to use (which won't be the case if your resolver is general purpose, i.e., doesn't apply to a particular property).
Workaround
Fortunately, there is always MapFrom
, which provides the flexibility that is lacking with both resolvers and formatters.
Converter interface
I ended up writing an interface to simply and flexibly handle what I believe is a very common scenario: two-way conversions...
public interface ITwoWayConverter<TInput, TOutput>
{
TOutput ConvertForward(TInput value);
TInput ConvertBackward(TOutput value);
}
Example converter:
public class PhoneNumberToString : ITwoWayConverter<long, string>
{
public string ConvertForward(long value)
{
return string.Format("{0:(###) ###-####}", Convert.ToInt64(value));
}
public long ConvertBackward(string value)
{
return Convert.ToInt64(Regex.Replace(value, @"\D", string.Empty));
}
}
Example usage:
Mapper.CreateMap<User, UserViewModel>()
.ForMember(dest => dest.PhoneNumber, opt => opt
.MapFrom(orig => new PhoneNumberToString().ConvertForward(orig.PhoneNumber)));
IValueFormatter is a interface, and can be tacked on to your existing classes or used in conjunction with what ever library it came out of, it looks like ValueResolver is a class that may have a broader range of use... In different words, IValueFormatter is probably used to help you use your classes with the library it came from, while value resolver is designed to help you use their classes in your code.
精彩评论