首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >Automapper自定义多对一转换

Automapper自定义多对一转换
EN

Stack Overflow用户
提问于 2015-05-18 18:24:05
回答 3查看 2.6K关注 0票数 17

自动映射器多对一转换

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

文档

这是来自documentationexample - one to one转换

代码语言:javascript
复制
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
}

案例

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

代码语言:javascript
复制
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;
    }
}

我想要实现这样的事情:

代码语言:javascript
复制
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;
    }
}

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

代码语言:javascript
复制
ValueResolver<Document, Currency>

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

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

例如:

代码语言:javascript
复制
Document document;
var documentDto = Mapper.Map<DocumentDto>(document); // and in this moment i have proper CurrencyDetails object!

谢谢你的建议。

我的解决方案

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

解决方案1 -使用接口包装一个类:

代码语言:javascript
复制
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;}
}

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

代码语言:javascript
复制
ValueResolver<ICurrencyHolder, Currency>

解决方案2 -将元素对象类型作为源元素,并通过反射获取值

代码语言:javascript
复制
ValueResolver<object, Currency>

这太可怕了!

EN

回答 3

Stack Overflow用户

发布于 2015-05-25 00:18:04

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

代码语言:javascript
复制
Mapper.CreateMap<Tuple<int,int>, Currency>()
   .ForMember(x => x.Currency, cfg => cfg.MapFrom(y => new Currency(y.Item1, y.Item2));

按如下方式调用映射器:

代码语言:javascript
复制
Mapper.Map<Tuple<int,int>, Currency>(Tuple.Create(doc.CurrencyId, doc.ExchangeRateId));
票数 8
EN

Stack Overflow用户

发布于 2015-05-21 14:42:47

可能你可以这样映射它:

代码语言:javascript
复制
Mapper.CreateMap<Source, Destination>()
      .ConstructUsing(s => Mapper.Map<Source, Currency>(s));

Mapper.CreateMap<Source, Currency>()
      .ForMember(dst => dst.CurrencySymbol, map => map.MapFrom(src => src.DocumentDto.CurrencySymbol))
      .ForMember(dst => dst.ExchangeRate , map => map.MapFrom(src => src.Document.ExchangeRate ));

也可以:

代码语言:javascript
复制
Mapper.CreateMap<Source, Destination>()
      .ConstructUsing(s => Mapper.Map<Source, Currency>(s));

Mapper.CreateMap<Source, Currency>()
      .ConstructUsing(s => Mapper.Map<DocumentDto, Currency>(s))
      .ConstructUsing(s => Mapper.Map<Document, Currency>(s));

Mapper.CreateMap<DocumentDto, Currency>();
Mapper.CreateMap<Document, Currency>();
票数 2
EN

Stack Overflow用户

发布于 2015-08-01 10:41:04

如果您确定要对每种文档类型执行此操作:

代码语言:javascript
复制
Document document;
var documentDto = Mapper.Map<DocumentDto>(document);

然后,您必须为它们中的每一个定义映射。因此,我肯定会采用ICurrencyHolder的想法,并使用如下的解析器:

对解析程序执行操作

代码语言:javascript
复制
public class CurrencyResolver : ValueResolver<ICurrencyHolder, Currency>
{
    protected override Currency ResolveCore(ICurrencyHolder source)
    {
        return new Currency(source.CurrencyId, source.ExchangeRateId);
    }
}

文档“类型”

代码语言:javascript
复制
public class Document : ICurrencyHolder
{
    public int CurrencyId { get; set; }
    public int ExchangeRateId { get; set; }
}

public class ExtendedDocument : ICurrencyHolder
{
    public DateTime SomeDate { get; set; }
    public int CurrencyId { get; set; }
    public int ExchangeRateId { get; set; }
}

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

及其映射:

代码语言:javascript
复制
Mapper.CreateMap<Document, DocumentDto>().ForMember(m => m.Currency, opt => opt.ResolveUsing<CurrencyResolver>());
Mapper.CreateMap<ExtendedDocument, DocumentDto>().ForMember(m => m.Currency, opt => opt.ResolveUsing<CurrencyResolver>());

准备就绪后,您可以像这样创建dto,并在映射阶段为您自动解析货币:

代码语言:javascript
复制
var dto = Mapper.Map<DocumentDto>(document);
var extendedDto = Mapper.Map<DocumentDto>(extendedDocument);
票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30300705

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档