如何在 Automapper 12.x ConstructUsing 中使用依赖注入

问题描述 投票:0回答:1

我们正在使用 Automapper 将 DTO 映射到实体。

为了确保创建的实体始终绑定到会话(我们使用 NHibernate),我们在 Automapper 配置中有以下内容:

var mapperConfig = new MapperConfiguration(cfg =>
{
    // Do other stuff
    cfg.Internal().ForAllMaps((tm, me) =>
    {
        if (typeof(IEntity).IsAssignableFrom(tm.DestinationType) &&
            typeof(IHasId).IsAssignableFrom(tm.SourceType))
        {
            var entityResolverType = typeof(EntityResolver<,>).MakeGenericType(tm.SourceType, tm.DestinationType);
            me.ConstructUsing((source, context) =>
            {
                var resolver = context.Options.ServiceCtor.Invoke(entityResolverType) as IEntityResolver;
                return resolver.Resolve(source);
            });
        }
    });
    cfg.AllowNullDestinationValues = true;
});

现在在 Automapper 12.x 中,无法再访问

ServiceCtor
中的
ResolutionContext
,我们必须考虑另一个解决方案。

我写了一个

ITypeConverter
。但这里的问题是,创建实体后,属性没有映射。

如果我使用

public class EntityTypeConverter<TModel, TEntity> : ITypeConverter<TModel, TEntity>
    where TModel : IHasId
    where TEntity : IEntity
{
    private readonly ISession session;

    public EntityTypeConverter(ISession session) { this.session = session; }

    public TEntity Convert(TModel source, TEntity destination, ResolutionContext context)
    {
        if (destination is null)
        {
            destination = session.Get<TEntity>(source.Id);
            destination ??= Activator.CreateInstance<TEntity>();
        }

        context.Mapper.Map(source, destination);
        return destination;
    }
}

我陷入了无限循环。

我也不能使用

AfterMap
,因为它是一个void方法,并且实体不是通过ref传递的。因此,我可以加载实体,但 Automapper 仍会返回未绑定的实例。

第三种解决方案是将会话传递给选项中的

Mapper.Map
,然后通过
Mapper.Items
访问它。但为此我必须修改很多代码行,而且也不能保证将来每个程序员都会记得这样做。

我不明白为什么这么复杂。这是一种不寻常的方法来编写一个通用类,为每个 DTO 从 session/dbContext 加载适当的实体,然后才将 DTO 中的新值映射到实体中?

有谁知道如何使用 DTO、构造函数、作用域和绑定实体来实现它?

感谢您的帮助。

c# nhibernate automapper
1个回答
0
投票

确保您的 DTO 属性是公共的,并且具有 public get set 修饰符。

© www.soinside.com 2019 - 2024. All rights reserved.