passing dependencies to value resolvers

1,259 views
Skip to first unread message

Jon Kruger

unread,
Mar 23, 2010, 9:07:41 AM3/23/10
to AutoMapper-users
One thing that has made testing difficult with AutoMapper is that
value resolvers are essentially created with a service location call,
which means that if I want my value resolvers to take in constructor
dependencies, I need to have StructureMap wired up in my unit tests to
serve up the dependency to the value resolver.

What I would really like is to be able to do something like this:

public class AutoMapperConfiguration
{
public void Configure()
{
Mapper.CreateMap<Book, BookViewModel>()
.ForMember(dest => dest.Discount,
opt =>
opt.ResolveUsing<BookDiscountResolver>().FromMember(src => src.Id));
}
}

public class BookToBookViewModelMapper :
IBookToBookViewModelMapper
{
private readonly ICalculateDiscountService
_calculateDiscountService;

public BookToBookViewModelMapper(ICalculateDiscountService
calculateDiscountService)
{
_calculateDiscountService = calculateDiscountService;
}

public BookViewModel Map(Book book)
{
// *** Notice the With() call here, this is what I would
like to be able to do (or something similar) ***

Mapper.With<ICalculateDiscountService>(_calculateDiscountService).Map(book);
}
}

public class BookDiscountResolver : ValueResolver<int, decimal>
{
private readonly ICalculateDiscountService
_calculateDiscountService;

public BookDiscountResolver(ICalculateDiscountService
calculateDiscountService)
{
_calculateDiscountService = calculateDiscountService;
}

public override decimal Resolve(int id)
{
return _calculateDiscountService.CalculateDiscount(id);
}
}

I'm still on the 1.0 version of AutoMapper, so maybe this is already
possible ... thoughts?

Jon

Jimmy Bogard

unread,
Mar 23, 2010, 9:32:08 AM3/23/10
to automapp...@googlegroups.com
Are you wanting the real versions of your resolvers, or stubs, or both?


--
You received this message because you are subscribed to the Google Groups "AutoMapper-users" group.
To post to this group, send email to automapp...@googlegroups.com.
To unsubscribe from this group, send email to automapper-use...@googlegroups.com.
For more options, visit this group at http://groups.google.com/group/automapper-users?hl=en.


Jon Kruger

unread,
Mar 23, 2010, 9:33:40 AM3/23/10
to automapp...@googlegroups.com
I want the real value resolvers, but I want to pass stubs into the resolver.

Jimmy Bogard

unread,
Mar 23, 2010, 5:01:32 PM3/23/10
to automapp...@googlegroups.com
One thing you could try is go through a ServiceLocator class, instead of StructureMap, something like:

public static class ServiceLocator {
    public static Func<Type, object> LocatorFunc = t => ObjectFactory.GetInstance(t);
    public static T GetInstance<T>() {
        return (T) LocatorFunc(typeof(T));
    }
    public static object GetInstance(Type type) {
        return LocatorFunc(type);
    }
}

Then your AM config:

Mapper.Initialize(cfg => {
   cfg.ConstructServicesUsing(t => ServiceLocator.GetInstance(t));
});

And in your test, you just replace the implementation of LocatorFunc with a function that returns your stubs.  Or with an auto-mocker, I've seen that too.

HTH,

Jimmy

Jon Kruger

unread,
Mar 23, 2010, 8:21:30 PM3/23/10
to automapp...@googlegroups.com
Good idea.  I think that will work.
Reply all
Reply to author
Forward
0 new messages