Reputation: 6863
I am using Automapper with our asp net core application. For the mappings from type A
-> B
and A
-> C
, I need an external service to inject some additional data. Therefore I have written a ValueResolver<T>
, where T
is either B
or C
. As C# doesn't have OR
operator for types, I use a generic T
here.
For clarity, my value resolver looks like this:
public class MyValueResolver<T>: IValueResolver<A, T, string>
{
private readonly IMyService _service;
public MyValueResolver(IMyService service)
{
_service = service;
}
public string Resolve(A source, T destination, string destMember, ResolutionContext context)
{
// do something using only source and _service.
return ...;
}
}
Now, in my startup I register automapper like this services.AddAutoMapper();
. Therefore, when I use it anywhere in my application, I just have to inject IMapper
in the constructor and it will resolve MyValueResolver
with IMyService
dependency automatically.
The problem arises in tests when I don't use DI and I need both MyValueResolver<B>
and MyValueResolver<C>
. I tried the following:
var mappingConfig = new MapperConfiguration(cfg => {
cfg.AddProfile(new MappingProfile());
cfg.ConstructServicesUsing(MyValueResolver =>
new MyValueResolver<B>(service));
cfg.ConstructServicesUsing(MyValueResolver =>
new MyValueResolver<C>(service));
});
var mapper = new Mapper(mappingConfig);
But this doesn't work, as it sees tries to use the latter statement for both cases and fails with an error that it cannot cast MyValueResolver<C>
to MyValueResolver<B>
. But the method doesn't accept types with generics defined (I assume it is a C# limitation?) like this cfg.ConstructServicesUsing(MyValueResolver<C> => new MyValueResolver<C>(service));
Is there any workaround for this, or maybe a different pattern I could use?
Upvotes: 0
Views: 829
Reputation: 6863
I was using ConstructServicesUsing
in a completely wrong way.
It takes a function , where Type - is a type of a ValueResolver
I want to resolve and Object
is the resolved instance. You should return null
for the types you don't want to resolve.
So it looks along the lines:
cfg => cfg.ConstructServicesUsing(type => type == typeof(MyValueResolver<B>) ? new MyValueResolver<B>(service) : null));
Credit goes to @LucianBargaoanu for this answer.
Upvotes: 1