Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/sorting/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 递归模型的自动映射条件映射_C#_Automapper - Fatal编程技术网

C# 递归模型的自动映射条件映射

C# 递归模型的自动映射条件映射,c#,automapper,C#,Automapper,我有一个递归模型类,定义如下: public class ItemFilterBlockGroup { public ItemFilterBlockGroup(string groupName, ItemFilterBlockGroup parent, bool advanced = false) { GroupName = groupName; ParentGroup = parent; Advanced = advanced;

我有一个递归模型类,定义如下:

public class ItemFilterBlockGroup
{
    public ItemFilterBlockGroup(string groupName, ItemFilterBlockGroup parent, bool advanced = false)
    {
        GroupName = groupName;
        ParentGroup = parent;
        Advanced = advanced;
        ChildGroups = new List<ItemFilterBlockGroup>();
    }

    public string GroupName { get; private set; }
    public bool Advanced { get; private set; }
    public ItemFilterBlockGroup ParentGroup { get; private set; }
    public List<ItemFilterBlockGroup> ChildGroups { get; private set; }
}
第一个CreateMap定义返回未触及的层次结构,第二个CreateMap定义(带有Advanced参数)返回修改后的层次结构(所有Advanced=true模型及其子模型都被排除在映射之外):


如何参数化showAdvanced条件并使用单个CreateMap定义实现相同的结果?我已经搜索了很多正确的解决方案,尝试使用ResolveUsing、CustomResolver,但都没有结果。

您可以使用自定义转换器,如下所示,您可以自定义映射设置

创建一个convert类

  internal class AccountConverter : TypeConverter<PD.IAccount, OD.IAccount>
{
    protected override OD.IAccount ConvertCore(PD.IAccount source)
    {
        var result = new Account()
        {
            CustomerNumber = source.CustomerNumber,
            EAccount = source.EAccount,
            EmailAddress = source.EmailAddress
        };

        return result;
    }
}
内部类AccountConverter:TypeConverter
{
受保护的覆盖OD.IAccount ConvertCore(PD.IAccount源)
{
var结果=新帐户()
{
CustomerNumber=source.CustomerNumber,
EAccount=source.EAccount,
EmailAddress=source.EmailAddress
};
返回结果;
}
}
然后像这样添加映射

Mapper.CreateMap<PD.IAccount, OD.IAccount>()
  .ConvertUsing(new AccountConverter());
Mapper.CreateMap()
.ConvertUsing(新AccountConverter());

您希望使用不属于对象的外部参数来控制逻辑。我相信最好的方法是使用一个映射,并根据您的标志过滤输入对象。像这样的

var blockGroupsTemp;
如果(显示高级)
blockGroupsTemp=blockGroups;
其他的
{
blockGroupsTemp=blockGroups.Where(x=>x.Advanced==false.ToList();
blockGroupsTemp.ForEach(s=>s.ChildGroups.RemoveAll(y=>y.Advanced==true));
}

var mappedViewModels=Mapper.Map(blockGroupsTemp)您可以使用上下文选项
集合在运行时将值传递给映射函数:

var showAdvanced = true;
var mappedViewModels = Mapper.Map<ObservableCollection<ItemFilterBlockGroupViewModel>>(
    blockGroups, 
    options => options.Items["includeAdvanced"] = showAdvanced);


如果使用弱类型字典值来传递标志参数对您来说不太合适,我建议将此逻辑封装在两个单独的方法中,如示例所示。

这只会过滤根对象的子对象-我需要过滤每个级别的子对象,这就是我问题中的第二个示例CreateMap所做的。我的重点是对源对象进行过滤,而不是使用映射器。我用一个过滤子组的选项更新了答案。你的答案仍然只过滤一个级别的子组-层次结构可能是无限深的。我希望做的是避免手动进行这种模型操作,因为AutoMaper显然能够做到这一点,因为我问题中的第二个CreateMap语句就是这样做的。好的,我看到了您尝试使用AutoMaper进行递归的方式。您是否尝试过像这里这样的配置映射,这如何帮助我在运行时有条件地映射?我需要一个单独的映射,它可以根据输入参数(我的问题示例中的showAdvanced布尔值)的不同表现。您可以在“ItemFilterBlockGroup”类中添加一个this show Advanced,该类是automapper中的源对象,然后您可以在“ConvertCore”中添加一个if条件方法,并检查其是否为真,否则执行此操作。这有意义吗。内部类AccountConverter:TypeConverter{受保护的重写OD.IAccount ConvertCore(PD.IAccount源){if(source.showAdvanced)…那么你是说我用只与我的观点相关的数据污染了我的对象模型?这不是我愿意做的事。还有一种方法可以改变automapper,但也不是很优雅,就像下面给出的那样。如果这对你来说也不起作用,那么就没有更干净的方法了在automapper中,您需要有一个条件映射,如上面的“XtremeBytes”所发布的。--bool showAdvanced=false;var tt=Mapper.Map(a1,e=>e.AfterMap((a,b)=>b.Name=showAdvanced?:a.Name));---这看起来更符合我的想法-但是我在理解如何构造视图模型时遇到了一些困难。因为视图模型是映射的同一类型,我不能在ConstructUsing调用中使用Mapper.Map。AutoMaper似乎正常地处理这种递归,但它似乎是使用ConstructUsing我将失去这个功能。在这一点上,我可能根本不使用AutoMapper,而只是编写一个递归方法来进行映射。我真正想做的是这样的:
Mapper.CreateMap().ForMember(dest=>dest.ChildGroups,opts=>opts.MapFrom(from=>(bool)context.Options.Items[“showAdvanced”]?from.ChildGroups:from.ChildGroups.Where(c=>c.Advanced==false))
但我认为无法从FormMember中访问选项。Items。@XVar,是的,我正在考虑它。尝试更新版本的地图创建代码
  internal class AccountConverter : TypeConverter<PD.IAccount, OD.IAccount>
{
    protected override OD.IAccount ConvertCore(PD.IAccount source)
    {
        var result = new Account()
        {
            CustomerNumber = source.CustomerNumber,
            EAccount = source.EAccount,
            EmailAddress = source.EmailAddress
        };

        return result;
    }
}
Mapper.CreateMap<PD.IAccount, OD.IAccount>()
  .ConvertUsing(new AccountConverter());
var showAdvanced = true;
var mappedViewModels = Mapper.Map<ObservableCollection<ItemFilterBlockGroupViewModel>>(
    blockGroups, 
    options => options.Items["includeAdvanced"] = showAdvanced);
Mapper.CreateMap<ItemFilterBlockGroup, ItemFilterBlockGroupViewModel>()
    .ForMember(destination => destination.ChildGroups, options => options.ResolveUsing(
        (resolution) =>
        {
            var includeAdvanced = (bool)resolution.Context.Options.Items["includeAdvanced"];
            var source = (ItemFilterBlockGroup)resolution.Context.SourceValue;
            if(includeAdvanced)
                return source.ChildGroups;
            else
                return source.ChildGroups.Where(c => c.Advanced == false);               
         }));