Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/heroku/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# 仅当目标属性不为null时使用DestinationValue_C#_.net_Automapper - Fatal编程技术网

C# 仅当目标属性不为null时使用DestinationValue

C# 仅当目标属性不为null时使用DestinationValue,c#,.net,automapper,C#,.net,Automapper,当我想使用UseDestinationValue方法中的行为,但仅当目标属性不是null时,如何配置自动映射 诸如此类: Mapper.CreateMap<Item, ItemViewModel>() .ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true)) 现在是用法示例。我有一个ItemViewModel类,我想将它映射到Item类 映射配

当我想使用
UseDestinationValue
方法中的行为,但仅当目标属性不是
null
时,如何配置自动映射

诸如此类:

Mapper.CreateMap<Item, ItemViewModel>()
    .ForMember(x => x.Details, _ => _.UseDestinationValue(dontUseWhenNullDestination: true))
现在是用法示例。我有一个
ItemViewModel
类,我想将它映射到
Item

映射配置:

    Mapper.CreateMap<Item, ItemViewModel>()
        .ForMember(x => x.Details, _ => _.UseDestinationValue())
由于存在
UseDestinationValue
,AutoMapper将离开
项.Details
实例,并仅设置
项.Details.Info
属性

  • 第二种情况-目标属性
    项。详细信息
    属性为空。现在我希望AutoMapper不要使用这个空实例,而是创建一个新实例。问题是如何配置映射以考虑这种情况

    逻辑如下所示:

    var item = new Item { 
        Details = new Details {
            Info = "Old text",
            ImportantData = "Data"
        }
    };
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel {
            Info = "New text"
        }
    };       
    
    Mapper.Map(itemViewModel, item);
    
    var item = new Item { 
        Details = null
    };
    
    var itemViewModel = new ItemViewModel { 
        Details = new DetailsViewModel {
            Info = "New text"
        }
    };
    
    Mapper.Map(itemViewModel, item);
    
    问题

    这里我遇到了一个问题,因为在映射之后,
    item.Details
    属性将为null(因为在本例中使用了
    UseDestinationValue
    ,它是
    null

  • 原因

    从数据库获取实体后,NHibernate将其放入代理中。因此,加载对象的
    Details
    属性的类型不是:
    ItemDetails
    ,而是
    itemDetailsHibernateProxy
    ——因此,当我以后要将此现有对象保存到数据库时,必须使用此类型。但是如果这个属性是
    null
    ,那么我不能使用空的目标值,所以Automapper应该创建一个新实例

    谢谢,
    克里斯

    我认为
    NullSubstitute
    选项适合您。见:

    编辑

    class ItemDetails {
        public string Info { get; set; }
        public string ImportantData { get; set; } // only in Domain, not in ViewModel
    }
    
    class Item {
        public ItemDetails Details { get; set; }
    }
    
    class ItemDetailsViewModel {
        public string Info { get; set; }
    }
    
    class ItemViewModel {
        public ItemDetailsViewModel Details { get; set; }
    }
    
    看起来您可能需要在映射中添加一些条件逻辑以了解详细信息(并跳过
    UseDestinationValue
    选项):

    .ForMember(d=>d.详细信息,
    o=>o.MapFrom(s=>s.Details==null?new ItemDetails():Mapper.Map(s.Details))
    
    我在处理NHibernate实体时遇到了同样的问题,我找到了非常简单的解决方案


    您应该在ItemViewModel构造函数中初始化Details属性。这样,目标值就永远不会为null。当然,这在更复杂的情况下(如抽象类)不起作用。

    也有同样的问题,但EF.Cryss关于使用BeforeMap的注释为我指明了正确的方向

    我最终得到的代码类似于:

    在Configure()方法中:

    Mapper.CreateMap<ItemViewModel, Item>()
               .AfterMap((s, d) => { MapDetailsAction(s, d); })
               .ForMember(dest => dest.Details, opt => opt.UseDestinationValue());
    
    Mapper.CreateMap()
    .AfterMap((s,d)=>{MapDetailsAction(s,d);})
    .ForMember(dest=>dest.Details,opt=>opt.UseDestinationValue());
    
    然后行动:

    Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
            {
                if (destination.Details == null)
                {
                    destination.Details = new Details();
                    destination.Details =
                        Mapper.Map<ItemViewModel, Item>(
                        source.Details, destination.Details);
                }
            };
    
    Action-MapDetailsAction=(源、目标)=>
    {
    if(destination.Details==null)
    {
    destination.Details=新细节();
    目的地,详情=
    地图绘制者(
    来源、详细信息、目的地、详细信息);
    }
    };
    
    那么,如果UseDestinationValue为null,您是否希望执行UseDestinationValue以外的操作?是的,当destination属性为null时,我还想执行其他操作。您能否提供一些工作示例代码,说明您希望映射的内容与Auotmapper当前的操作。我只是不明白您的要求。我希望automapper使用destination属性然后设置ItemDetails类的内部属性。但这应该只在Details属性不为null时起作用(因为我想使用此实例),因此,当Details属性为null时,不要使用此null值,而是创建一个新实例。很遗憾,不是。现在我要做的是检查BeforeMap操作中的目标属性值是否为null。源值为null时,NullSubstitute很有用。
    Action<ItemViewModel, Item> MapDetailsAction = (source, destination) =>
            {
                if (destination.Details == null)
                {
                    destination.Details = new Details();
                    destination.Details =
                        Mapper.Map<ItemViewModel, Item>(
                        source.Details, destination.Details);
                }
            };