问题
With AutoMapper, when using ConvertUsing to define a custom mapping for a type that is a container, I often need to call IMappingEngine.Map inside the mapping function. This is necessary because it allows-me to reuse the definition of the child mapping.
CreateMap<Order, OrderModel>()
.ConvertUsing(o => new OrderModel(
o.Id,
o.ShippingAddress,
mapper.Map<IList<OrderItemModel>>(o.Items)
));
In order to do this, I need a reference to IMappingEngine. When the mapping engine is being configured, I don't have a reference to it that can be captured in the ConvertUsing argument. A simple solution is to have a static reference to it somewhere, but I would like to avoid it.
Is there a way to get a reference to the current IMappingEngine inside a mapping that uses ConvertUsing?
回答1:
This answer is based on your original revision which included additional code
If you take a look at the article by Jimmy Bogard on Automapper and IOC he notes the following:
The MappingEngine, unlike our Configuration object, does not need any special caching/lifetime behavior. The MappingEngine is very lightweight, as it’s really a bunch of methods doing interesting things with Configuration. MappingEngine can be singleton if we want, but there’s no need.
(There is updated sample IOC code for the latest version of Automapper on github)
As long as your ConfigurationStore
is a singleton and requests for IConfiguration
and IConfigurationProvider
from your DI container resolve to this singleton instance, the article (and code examples) advocates that is fine to create new instances of the MappingEngine
when injected.
Based on the above, aside from not registering your ConfigurationStore
as a singleton instance (I assume, I'm not familiar with ninject) and not binding this instance to the IConfiguration
your final implementation of MappingProfile
in your original revision is actually an acceptable solution. It is OK for this to not be the same MappingEngine
instance.
However, going by your sample usage in your question it may be worth considering Scenario 2 in the article. If you have no requirement to inject configuration throughout your application and only the IMappingEngine
, then you can rely on the static Mapper
class for the configuration and lifetime management. In summary your changes to adopt this would be:
Remove the
IConfigurationProvider
related wiring in the build-up of your container (in theMappingModule
).Switching your
MappingProfile
to use the staticMapper
classCreateMap<Order, OrderModel>() .ConvertUsing(o => new OrderModel( o.Id, o.ShippingAddress, Mapper.Map<IList<OrderItemModel>>(o.Items) //use static Mapper class )); CreateMap<OrderItem, OrderItemModel>();
Adding the
Profile
to theMapper
(perhaps in theMappingModule
?), and doing any other configuration through theMapper
:Mapper.AddProfile(new MappingProfile());
Binding
IMappingEngine
in the ninject container to theMapper.Engine
property.
回答2:
You can use the static Mapper.Map<IList<OrderItemModel>>(o.Items)
instead of your instance of IMappingEngine
. It contains a reference to the engine that is lazily instantiated the first time it is used.
来源:https://stackoverflow.com/questions/9282819/calling-imappingengine-map-inside-custom-mapping