c# - Automapper自定义多对一转换

标签 c# mapping converter automapper dto

Automapper 多对一转换

如何将多个属性的值从源对象转换为目标对象中的单一类型? 我可以在这种情况下使用 Value Resolvers ?或者有更好的解决方案?

文档

这里是 example来自 documentation - 一对一转换

Mapper.CreateMap<Source, Destination>()
    .ForMember(dest => dest.Total,
        opt => opt.ResolveUsing<CustomResolver>().FromMember(src => src.SubTotal));
Mapper.CreateMap<OtherSource, OtherDest>()
    .ForMember(dest => dest.OtherTotal,
        opt => opt.ResolveUsing<CustomResolver>().FromMember(src => src.OtherSubTotal));

public class CustomResolver : ValueResolver<decimal, decimal> {
// logic here
}

案例

我想将两个对象转换为一个对象(多对一转换)。例如:

public class Document
{
    public int CurrencyId {get; set;}
    public int ExchangeRateId {get; set;}
}

public class DocumentDto
{
    public Currency Currency {get; set;}
}

public class CurrencyDetails
{
    public Currency Currency {get; private set;}
    public ExchangeRate ExchangeRate {get; private set;}

    public CurrencyDetails(Currency currency, ExchangeRate exchangeRate)
    {
        Currency = currency;
        ExchangeRate = exchangeRate;
    }
}

我想实现这样的目标:

public class CurrencyResolver : ValueResolver<int, int, CurrencyDetails>
{
    protected override Currency ResolveCore(int currencyId, int exchangeRateId)
    {
        var currency = new Currency(currencyId); //simplified logic
        var exchangeRate = new ExchangeRate(exchangeRateId);

        var currencyDetails = new CurrencyDetails(currency, exchangeRate);
        return currencyDetails;
    }
}

我知道我可以将整个对象作为源对象传递,但对我来说这不是解决方案:

ValueResolver<Document, Currency>

我不能使用完整的对象,因为我有很多文档类型而且我不想为每个文档创建新的解析器。 在我的情况下也不允许忽略元素(用于手动转换)。货币转换逻辑必须由 AutoMapper 执行。

转换发生在后台(在主要主题的转换过程中)对我来说很重要。

例如:

Document document;
var documentDto = Mapper.Map<DocumentDto>(document); // and in this moment i have proper CurrencyDetails object!

感谢您的建议。

我的解决方案

我想到了两个解决方案,但我不喜欢它们(太脏了)

解决方案 1 - 用接口(interface)包装一个类:

public interface ICurrencyHolder
{
    int CurrencyId {get; set;}
    int ExchangeRateId {get; set;}
}

public class Document : ICurrencyHolder
{
    public int CurrencyId {get; set;}
    public int ExchangeRateId {get; set;}
}

并使用具有以下参数的解析器:

ValueResolver<ICurrencyHolder, Currency>

方案二 - 以源元素对象类型为源,通过反射取值

ValueResolver<object, Currency>

这太可怕了!

最佳答案

如果我理解正确,您需要进行以下映射:从 (CurrencyId, ExchangeRateId) 到 Currency。您可以使用 Tuple(it is a standard .Net class 在这些情况下非常方便)实现它:

Mapper.CreateMap<Tuple<int,int>, Currency>()
   .ForMember(x => x.Currency, cfg => cfg.MapFrom(y => new Currency(y.Item1, y.Item2));

按如下方式调用映射器:

Mapper.Map<Tuple<int,int>, Currency>(Tuple.Create(doc.CurrencyId, doc.ExchangeRateId));

关于c# - Automapper自定义多对一转换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/30300705/

相关文章:

c# - .NET Windows 窗体设计时规则

c - 仅映射文件 C 的第一个字母

c# - 将 float 转换为 int 数将导致 int 无效

c# - 如果行存在则执行更新,否则执行插入

c# - 强大的 .NET map API?

c# - ValueInjector 未映射属性

spring - Spring MVC 格式化程序和转换器之间的区别

java - 使用 Java 泛型为实体实现转换器

ffmpeg PNG - MP4 - 打开输入文件时出错 : invalid argument

c# - 如何以编程方式设置图像源