【问题标题】:Projection or Custom Value Resolvers with new Multi Lingual Mappings具有新的多语言映射的投影或自定义值解析器
【发布时间】:2018-07-24 12:43:58
【问题描述】:

我正在使用最新版本的 ASP.Net Boilerplate(版本 3.7.2)。我目前正在使用新的多语言实体。

我在将 1 个实体自动映射到 Dto 时遇到问题,因为它不仅需要多语言方面,还需要其中一个属性的投影/自定义解析器。

到目前为止,所有映射都正常工作。我遵循了ASP.NET Boilerplate Documentation

上的文档
[Table("CategoryItems")]
public class CategoryItem : BaseClass, IMultiLingualEntity<CategoryItemTranslation>
{
    /// <summary>
    /// Gets or Sets the Category Item Display Order
    /// </summary>
    public int DisplayOrder { get; set; }

    /// <summary>
    /// Gets or Sets Catalog Categories
    /// </summary>
    public virtual ICollection<CatalogItem> CatalogItems { get; set; } = new HashSet<CatalogItem>();

    ...

    /// <summary>
    /// Gets or Sets all the Entity Translations
    /// </summary>
    public virtual ICollection<CategoryItemTranslation> Translations { get; set; } = new HashSet<CategoryItemTranslation>();
}


[Table("CategoryItemTranslations")]
public class CategoryItemTranslation : IEntityTranslation<CategoryItem>
{
    /// <summary>
    /// Get or Set Category Item Name
    /// </summary>
    public string CategoryItemName { get; set; }

    /// <summary>
    /// Gets or Sets Link to Category Item
    /// </summary>
    public CategoryItem Core { get; set; }

    /// <summary>
    /// Gets or Sets Link to Core Id
    /// </summary>
    public int CoreId { get; set; }

    /// <summary>
    /// Gets or Sets the Language
    /// </summary>
    public string Language { get; set; }
}


public class ReadCategoryItemFilterDto : PhantomEntityDto
{
    public string CategoryItemName { get; set; }

    ...

    public int ItemCount { get; set; }

    ...
}

在 ApplicationModule 类的 Initialize 中使用 Create MultiLingual Map 代码:

cfg.CreateMultiLingualMap<CategoryItem, CategoryItemTranslation, ReadCategoryItemFilterDto>(new MultiLingualMapContext(IocManager.Resolve<ISettingManager>()));

翻译实体中的 CategoryItemName 正确映射到 ReadCategoryItemFilterDto 上的 CategoryItemName。

现在我需要将 CatalogItems Count 映射到 Dto 上的 ItemCount。

我已尝试添加到映射配置器:

cfg.CreateMap<CategoryItem, ReadCategoryItemFilterDto>()
    .ForMember(dest => dest.ItemCount, opts => opts.MapFrom(src => src.CatalogItems.Count));

cfg.CreateMap<CategoryItem, ReadCategoryItemFilterDto>()
    .ForMember(dest => dest.ItemCount, opts => opts.ResolveUsing(new CatalogItemFilterCountResolver()));

使用

public class CatalogItemFilterCountResolver : IValueResolver<CategoryItem, ReadCategoryItemFilterDto, int>
{
    public int Resolve(CategoryItem source, ReadCategoryItemFilterDto destination, int m, ResolutionContext context)
    {
        return source.CatalogItems.Count;
    }
}

如果我在 CreateMultiLingualMap 之前添加此地图,则 CatalogItemName 地图正确,但 ItemCount 失败。 如果我将 Projection 或 Resolver 放在 CreateMultiLingualMap 之后,则 ItemCount 映射正确,但 CatalogItemName 映射失败。

如何创建地图配置文件以允许映射这两个属性?

谢谢。

【问题讨论】:

    标签: asp.net-core automapper aspnetboilerplate


    【解决方案1】:

    对于您的情况,您不需要使用扩展名CreateMultiLingualMap。 您可以创建自己的包含多语言映射的映射定义。

    就是这样处理的;

    configuration.CreateMap<CategoryItem, ReadCategoryItemFilterDto>()
        .BeforeMap((source, destination, context) =>
        {
            var translation = source.Translations.FirstOrDefault(pt => pt.Language == CultureInfo.CurrentUICulture.Name);
            if (translation != null)
            {
                context.Mapper.Map(translation, destination);
                return;
            }
    
    
            var multiLingualMapContext = new MultiLingualMapContext(IocManager.Instance.Resolve<ISettingManager>());
            var defaultLanguage = multiLingualMapContext.SettingManager.GetSettingValue(LocalizationSettingNames.DefaultLanguage);
    
            translation = source.Translations.FirstOrDefault(pt => pt.Language == defaultLanguage);
    
            if (translation != null)
            {
                context.Mapper.Map(translation, destination);
                return;
            }
    
            translation = source.Translations.FirstOrDefault();
            if (translation != null)
            {
                context.Mapper.Map(translation, destination);
            }
    
        }).ForMember(dest => dest.ItemCount, opts => opts.MapFrom(src => src.CatalogItems.Count));
    

    【讨论】:

    • 谢谢,但是 CategoryItemTranslation 实体和 ReadCategoryItemFilterDto 之间的 Automap 仍然出错。它对未映射的属性(包括 ItemCount)不满意。我尝试为所有这些属性添加 ForMember 无济于事。
    • 您需要忽略 dto .Ignore(record =&gt; record.Field) 中所有不存在的属性
    • 我尝试在 BeforeMap 之后添加.ForAllOtherMembers(opts =&gt; opts.Ignore());。但是,该错误仍然表明在 context.Mapper.Map(translation, destination) 行的 BeforeMap 中映射失败。谢谢。
    • 好的,我已经解决了。我还必须在 Transaltion Entity 和 Dto 之间添加另一个 Map 以及接受的答案。所以在我的情况下:cfg.CreateMap&lt;CategoryItemTranslation, ReadCategoryItemFilterDto&gt;() .ForMember(dest =&gt; dest.CategoryItemName, opts =&gt; opts.MapFrom(src =&gt; src.CategoryItemName)) .ForAllOtherMembers(opts =&gt; opts.Ignore()); 是必需的。感谢您的所有帮助。
    【解决方案2】:

    https://aspnetboilerplate.com/Pages/Documents/Multi-Lingual-Entities#createmultilingualmap

    configuration.CreateMultiLingualMap<CategoryItem, CategoryItemTranslation, ReadCategoryItemFilterDto>(context)
    .EntityMap.ForMember(dest => dest.ItemCount, opt => opt.MapFrom(src => src.CatalogItems.Count));
    

    【讨论】:

    • 这解决了最新版本的框架中的问题。但是,这在我当时开发的版本(v3.7.2)中是不可能的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-03-16
    • 1970-01-01
    • 2014-08-05
    • 2011-01-12
    • 1970-01-01
    • 1970-01-01
    • 2023-04-08
    相关资源
    最近更新 更多