AutoMapper:“ ละเว้นส่วนที่เหลือ” หรือไม่


206

มีวิธีบอก AutoMapper ให้ละเว้นคุณสมบัติทั้งหมดยกเว้นคุณสมบัติที่แมปอย่างชัดเจนหรือไม่

ฉันมีคลาส DTO ภายนอกซึ่งมีแนวโน้มที่จะเปลี่ยนจากภายนอกและฉันต้องการหลีกเลี่ยงการระบุคุณสมบัติแต่ละรายการให้ถูกละเว้นอย่างชัดเจนเนื่องจากการเพิ่มคุณสมบัติใหม่จะทำให้ฟังก์ชันการทำงาน (ทำให้เกิดข้อยกเว้น) เมื่อพยายามแมปเข้ากับวัตถุของฉันเอง


1
ด้วย ValueInjecter valueinjecter.codeplex.com/documentationคุณสร้าง ValueInjections ที่มีการทำแผนที่ alghorithm และแผนที่ระหว่างคุณสมบัติเฉพาะและพวกเขาไม่สนใจคุณสมบัติที่เหลือ
Omu

24
สำหรับผู้ที่ใช้ Automapper> รุ่น 5 ให้ข้ามเพื่อดูรายละเอียดคำตอบ.ForAllOtherMembers(opts => opts.Ignore())
Jack Ukleja

@Schneider ".ForAllOtherMembers (opts => opts.Ignore ())" แตกต่างกับส่วนขยาย "IgnoreAllNonExisting" ที่นี่ความแตกต่างที่สำคัญคือถ้าคุณไม่ได้กำหนดค่าคุณสมบัติอย่างชัดเจนด้วย ".ForAllOtherMembers (opts => opts.Ignore () )) "คุณจะไม่ได้รับการแมป ใช้ "IgnoreAllNonExisting" โดยไม่มีคุณสมบัติการกำหนดค่าอย่างชัดเจนคุณยังคงได้รับการแมปคุณสมบัติ (คุณสมบัติที่มีชื่อเดียวกัน) ที่มีค่า
มังกร

ใช่. ForAllOtherMembers คือคำตอบ คำตอบ IgnoreUnmapped ไม่ได้ทำอะไรนอกจากทำให้ config-valid-assert ผ่านเนื่องจากสมาชิกที่ไม่ได้แมปจะถูกละเว้น
N73k

น่าสังเกตว่าเมื่อทำเช่นนี้คุณซ่อนการเปลี่ยนแปลงที่อาจเกี่ยวข้องหรือสำคัญในคลาสที่แมปไว้อย่างชัดเจน การมีการแมปที่ชัดเจนสำหรับทุก ๆ คุณสมบัติจะทำให้คุณมีการทดสอบที่ไม่สมบูรณ์เมื่อใดก็ตามที่มีการเปลี่ยนแปลงคลาสที่แม็พบังคับให้คุณประเมินอย่างถูกต้อง (เนื่องจากคุณมีการทดสอบที่AssertConfigurationIsValid()เรียก) ด้วยเหตุนี้ฉันจึงพิจารณา "ละเว้นส่วนที่เหลือ" antipattern
Arve Systad

คำตอบ:


83

นี่เป็นวิธีส่วนขยายที่ฉันเขียนซึ่งไม่สนใจคุณสมบัติที่ไม่มีอยู่ทั้งหมดบนปลายทาง ไม่แน่ใจว่ามันจะยังคงมีประโยชน์เพราะคำถามมีอายุมากกว่าสองปี แต่ฉันพบปัญหาเดียวกันกับที่ต้องเพิ่มการละเว้นการโทรด้วยตนเองจำนวนมาก

public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>
(this IMappingExpression<TSource, TDestination> expression)
{
    var flags = BindingFlags.Public | BindingFlags.Instance;
    var sourceType = typeof (TSource);
    var destinationProperties = typeof (TDestination).GetProperties(flags);

    foreach (var property in destinationProperties)
    {
        if (sourceType.GetProperty(property.Name, flags) == null)
        {
            expression.ForMember(property.Name, opt => opt.Ignore());
        }
    }
    return expression;
}

การใช้งาน:

Mapper.CreateMap<SourceType, DestinationType>()
                .IgnoreAllNonExisting();

อัปเดต : เห็นได้ชัดว่านี่ไม่ทำงานอย่างถูกต้องหากคุณมีการแมปที่กำหนดเองเพราะมันเขียนทับพวกเขา ฉันเดาว่ามันยังสามารถใช้งานได้ถ้าโทร IgnoreAllNonExisting ก่อนจากนั้นจึงทำการแมปที่กำหนดเองในภายหลัง

schdr มีวิธีแก้ปัญหา (เป็นคำตอบสำหรับคำถามนี้) ซึ่งใช้Mapper.GetAllTypeMaps()เพื่อค้นหาว่าคุณสมบัติใดที่ไม่ได้ถูกแมป ดูเหมือนจะเป็นทางออกที่แข็งแกร่งสำหรับฉัน


ฉันไม่เคยใช้ AutoMapper มาก่อน แต่ฉันจะตอบคำถามของคุณถ้ามันเหมาะกับคุณ :)
Igor Brejc

2
ขอบคุณ !! ฉันพบว่ามันมีประโยชน์มาก การเพิกเฉยต่อคุณสมบัติเป็นรายบุคคลคือการเอาชนะจุดประสงค์ของการใช้ออปเปอร์แมปในสถานการณ์ของฉัน
Daniel Robinson

ดูคำตอบต่อไปสำหรับผู้ที่ไม่มีปัญหาการเขียนทับ
Jason Coyne

3
วิธีนี้ควรเป็นรหัสพื้นเมืองของ autoMapper! ดีมากขอบคุณ!
Felipe Oriani

2
FYI, Jimmy ตัวเอง (นักเขียนของ AutoMapper) ได้แสดงความคิดเห็นด้านล่างว่าคำตอบของ @ nazim นั้นถูกต้องสำหรับรุ่น 5+
Worthy7

244

จากสิ่งที่ฉันเข้าใจคำถามก็คือมีเขตข้อมูลบนปลายทางซึ่งไม่มีเขตข้อมูลที่แมปในแหล่งที่มาซึ่งเป็นสาเหตุที่คุณกำลังมองหาวิธีที่จะละเว้นเขตข้อมูลปลายทางที่ไม่ได้แมป

แทนที่จะใช้และใช้วิธีการขยายเหล่านี้คุณก็สามารถใช้

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Source);  

ตอนนี้ automapper รู้ว่ามันจะต้องตรวจสอบเท่านั้นว่าเขตข้อมูลที่มาทั้งหมดจะถูกแมป แต่ไม่ใช่วิธีอื่น ๆ

คุณยังสามารถใช้:

Mapper.CreateMap<sourceModel, destinationModel>(MemberList.Destination);  

10
คำตอบนี้ควรมี upvotes มากขึ้นบางทีอาจถูกทำเครื่องหมายเป็นคำตอบ มันแก้ปัญหาของฉันและในทำนองเดียวกันMemberList.Destinationจะแก้ปัญหา ops
Tedd Hansen

1
มันจะไม่ทำงานถ้าคุณต้องการที่จะเพิกเฉยต่อคุณสมบัติไม่กี่แห่งทั้งที่มาและปลายทาง :)
RealWillyWoka

62
สำหรับทุกคนที่มาในภายหลังนี่คือคำตอบที่ถูกต้องสำหรับ 5.0
Jimmy Bogard

3
ดูดี แต่ไม่ได้ผลสำหรับฉัน .. ฉันลองใช้แหล่งที่มาและปลายทางแล้ว แต่มันก็บ่นเกี่ยวกับวัตถุคุณสมบัติเดียวกันที่ขาดหายไปในแผนที่
Sonic Soul

1
ใช้ 6.0.2 และมันไม่ทำงาน คุณสมบัติใด ๆ ที่ไม่ได้ถูกแมปจากปลายทางไปยังแหล่งที่มาเขียนทับคุณสมบัติในแหล่งที่มาด้วย nulls และ 0s บวกกับรหัสไม่ได้ทำให้ชัดเจนกับสิ่งที่คุณทำโดยเฉพาะอย่างยิ่งถ้าคุณทำงานในทีม ว่าทำไมฉันไม่ชอบอย่างมากรหัสนี้และทำไมฉันชอบคำพูดของทางเลือกเช่นคำตอบที่แนะ "IgnoreAllNonExisting"
sksallaj

222

ฉันได้อัปเดตส่วนขยายของ Can Gencer เพื่อไม่เขียนทับแผนที่ที่มีอยู่

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var sourceType = typeof (TSource);
    var destinationType = typeof (TDestination);
    var existingMaps = Mapper.GetAllTypeMaps().First(x => x.SourceType.Equals(sourceType) && x.DestinationType.Equals(destinationType));
    foreach (var property in existingMaps.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

การใช้งาน:

Mapper.CreateMap<SourceType, DestinationType>()
                .ForMember(prop => x.Property, opt => opt.MapFrom(src => src.OtherProperty))
                .IgnoreAllNonExisting();

4
+1 ขอขอบคุณที่โพสต์โซลูชันนี้ ฉันใช้เวลาหลายชั่วโมงในการหาข้อผิดพลาดแปลก ๆ เมื่อฉันใช้โซลูชันในgoo.gl/rG7SLจนกว่าฉันจะสะดุดกับโพสต์นี้อีกครั้ง
Nordin

3
ฉันแนะนำวิธีของ Yohanb ด้านล่างนี้ มีบางมุมที่ไม่สามารถใช้งานได้
Jon Barker

3
สามารถทำได้ใน AutoMapper 4.2 หรือไม่ ( Mapper.GetAllTypeMaps()เลิกใช้แล้ว)
mrmashal

14
สำหรับ AutoMapper 5+ รุ่นเพียงแทนที่ด้วยMapper.GetAllTypeMaps() Mapper.Configuration.GetAllTypeMaps()นี่คือการอ้างอิง github.com/AutoMapper/AutoMapper/issues/1252
Sergey G.

5
สำหรับคนใหม่ที่อ่านข้อความนี้ คำตอบนี้สำหรับ AutoMapper 2 และในขณะที่เขียนความคิดเห็นนี้เราอยู่ที่รุ่น 6 นี่คือแฮ็คและวิธีที่สะอาดกว่านี้คือการใช้ MemberList enum ดูที่ Github ฉบับที่ 1839 และทางออกที่ดีกว่า github.com/AutoMapper/AutoMapper/issues/1839ตัวอย่างเช่น: stackoverflow.com/a/31182390/3850405
Ogglas

83

ฉันสามารถทำสิ่งนี้ด้วยวิธีต่อไปนี้:

Mapper.CreateMap<SourceType, DestinationType>().ForAllMembers(opt => opt.Ignore());
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 1 here*/);
Mapper.CreateMap<SourceType, DestinationType>().ForMember(/*Do explicit mapping 2 here*/);
...

หมายเหตุ: ฉันใช้ AutoMapper v.2.0


4
ขอบคุณมาก! มันทำงานเหมือนจับใจ ฉันพยายามโทรครั้งแรก แต่ ForAllMembers เพิ่งส่งคืนโมฆะ :( มันไม่ชัดเจนว่า IgnoreAll ก่อนหน้าสามารถแก้ไขได้ในภายหลัง
SeriousM

5
ฉันไม่ชอบวิธีนี้เช่นกัน .. ถ้าคุณมีสมาชิก 50 คนและคุณต้องการที่จะเพิกเฉย 25 .. แล้วประเด็นของ automapper คืออะไรถ้าคุณยังไม่สนใจสมาชิก 25 คน หากชื่อตรงกันและมีคุณสมบัติที่ไม่ตรง .. ทำไมไม่บอกให้ชัดเจนว่า automapper ไม่จับคู่กับคุณสมบัติที่ไม่ได้แมปและผ่านการพิมพ์ทั้งหมด?
sksallaj

71

AutoMapper เวอร์ชัน 5.0.0-beta-1 แนะนำForAllOtherMembersวิธีการขยายดังนั้นตอนนี้คุณสามารถทำได้:

CreateMap<Source, Destination>()
    .ForMember(d => d.Text, o => o.MapFrom(s => s.Name))
    .ForMember(d => d.Value, o => o.MapFrom(s => s.Id))
    .ForAllOtherMembers(opts => opts.Ignore());

โปรดทราบว่ามีข้อได้เปรียบในการทำแผนที่แต่ละคุณสมบัติอย่างชัดเจนเนื่องจากคุณจะไม่ได้รับปัญหาของการทำแผนที่ความล้มเหลวอย่างเงียบ ๆ ที่เกิดขึ้นเมื่อคุณลืมที่จะทำแผนที่คุณสมบัติ

บางทีในกรณีของคุณอาจเป็นการดีที่จะไม่สนใจสมาชิกคนอื่น ๆ ทั้งหมดและเพิ่ม a TODOเพื่อกลับมาทำอย่างชัดเจนหลังจากความถี่ของการเปลี่ยนแปลงในชั้นเรียนนี้สงบลง


3
น่าทึ่งนี่ใช้เวลาจนถึงเวอร์ชัน 5 ดูว่ามีผู้โหวตกี่คนและพยายามตอบคำถามนี้ ... มีอะไรผิดปกติกับการกำกับดูแลของ Automapper ที่ฉันสงสัย?
Jack Ukleja

ขอบคุณสำหรับสิ่งนี้พาฉันสักครู่เพื่อเลื่อนลงไป แต่สิ่งนี้ แต่มันทำงานได้อย่างสมบูรณ์
cobolstinks

2
คุณสามารถใส่บรรทัด ForAllOtherMembers ก่อนและทุกอย่างจะทำงานเหมือนเดิมซึ่งดีถ้าคุณมีการกำหนดค่าระดับฐานบางอย่าง
N73k

นี่คือวิธีการที่ต้องการ สงสัยว่า OP จะเปลี่ยนคำตอบที่ยอมรับได้ไหม?
Chase Florell

1
มีเทียบเท่าเพื่อละเว้นคุณสมบัติในวัตถุต้นฉบับหรือไม่ สิ่งที่ชอบForAllOtherSourceMembers?
SuperJMN

44

ในฐานะของ AutoMapper 5.0 .TypeMapคุณสมบัติที่IMappingExpressionหายไปหมายถึงโซลูชัน 4.2 ไม่ทำงานอีกต่อไป ฉันได้สร้างโซลูชันที่ใช้ฟังก์ชั่นดั้งเดิม แต่มีไวยากรณ์แตกต่างกัน:

var config = new MapperConfiguration(cfg =>
{
    cfg.CreateMap<Src, Dest>();
    cfg.IgnoreUnmapped();        // Ignores unmapped properties on all maps
    cfg.IgnoreUnmapped<Src, Dest>();  // Ignores unmapped properties on specific map
});

// or add  inside a profile
public class MyProfile : Profile
{
   this.IgnoreUnmapped();
   CreateMap<MyType1, MyType2>();
}

การดำเนินงาน:

public static class MapperExtensions
{
    private static void IgnoreUnmappedProperties(TypeMap map, IMappingExpression expr)
    {
        foreach (string propName in map.GetUnmappedPropertyNames())
        {
            if (map.SourceType.GetProperty(propName) != null)
            {
                expr.ForSourceMember(propName, opt => opt.Ignore());
            }
            if (map.DestinationType.GetProperty(propName) != null)
            {
                expr.ForMember(propName, opt => opt.Ignore());
            }
        }
    }

    public static void IgnoreUnmapped(this IProfileExpression profile)
    {
        profile.ForAllMaps(IgnoreUnmappedProperties);
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Func<TypeMap, bool> filter)
    {
        profile.ForAllMaps((map, expr) =>
        {
            if (filter(map))
            {
                IgnoreUnmappedProperties(map, expr);
            }
        });
    }

    public static void IgnoreUnmapped(this IProfileExpression profile, Type src, Type dest)
    {
        profile.IgnoreUnmapped((TypeMap map) => map.SourceType == src && map.DestinationType == dest);
    }

    public static void IgnoreUnmapped<TSrc, TDest>(this IProfileExpression profile)
    {
        profile.IgnoreUnmapped(typeof(TSrc), typeof(TDest));
    }
}

3
คุณจะใช้สิ่งนี้ในการCreateMap<TSource,TDest>()แสดงออกที่ถูกล่ามโซ่ในProfile?
jmoerdyk

2
ขอบคุณสำหรับสิ่งนี้. เมธอด GetUnmappedPropertyNames ส่งคืนชื่อคุณสมบัติที่ไม่ได้แมปทั้งที่ต้นทางและปลายทางซึ่งดูเหมือนว่าจะพังบนแผนที่ย้อนกลับดังนั้นฉันต้องทำการเปลี่ยนแปลงเล็กน้อยเพื่อ IgnoreUnmapped เพื่อตรวจสอบว่าคุณสมบัติที่ไม่ได้แมปนั้นอยู่ในแหล่งที่มาหรือปลายทางและไม่สนใจ ตาม นี่คือซอแสดงให้เห็นถึงปัญหาและการปรับปรุง: dotnetfiddle.net/vkRGJv
Mun

1
ฉันได้อัปเดตคำตอบของฉันเพื่อรวมสิ่งที่คุณค้นพบแล้ว - ฉันไม่ได้ใช้การจับคู่แหล่งข้อมูลดังนั้นจึงไม่เจอสิ่งนี้! ขอบคุณ
ริชาร์ด

1
สิ่งนี้ใช้ไม่ได้กับ PCL หากไม่มีการสะท้อน แต่ GetProperty (propName) ไม่มีอยู่
George Taskos

ฉันไม่เห็นว่าสิ่งนี้เป็นวิธีแก้ปัญหาของคำถามได้อย่างไร คุณสมบัติ unmapped มีอยู่แล้วจะได้รับการละเว้น - เพราะพวกเขามีการแม็ป โปสเตอร์กล่าวว่า "คุณจะเพิกเฉยต่ออุปกรณ์ประกอบฉากได้อย่างไรหากไม่ได้ทำการแมปอย่างชัดเจน " นั่นหมายความว่าถ้าฉันมี Src.MyProp และ Dest.MyProp การทำแผนที่นั้นควรจะถูกละเว้นเว้นแต่จะมีการเรียก MapFrom & ForMember สำหรับ MyProp อย่างชัดเจน ดังนั้นการทำแผนที่เริ่มต้นจะต้องถูกละเว้น สิ่งเดียวที่โซลูชันนี้ทำคือทำให้สิ่งที่ config-valid-assert ยืนยันผ่านซึ่งคุณไม่ต้องการสำหรับการทำแผนที่ในการทำงาน
N73k

17

ไม่กี่ปีที่ผ่านมาตั้งแต่คำถามถูกถาม แต่วิธีการขยายนี้ดูสะอาดสำหรับฉันโดยใช้ AutoMapper รุ่นปัจจุบัน (3.2.1):

public static IMappingExpression<TSource, TDestination> IgnoreUnmappedProperties<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    var typeMap = Mapper.FindTypeMapFor<TSource, TDestination>();
    if (typeMap != null)
    {
        foreach (var unmappedPropertyName in typeMap.GetUnmappedPropertyNames())
        {
            expression.ForMember(unmappedPropertyName, opt => opt.Ignore());
        }
    }

    return expression;
}

16

สำหรับผู้ที่ใช้API ที่ไม่คงที่ในรุ่น 4.2.0 และสูงกว่าสามารถใช้วิธีการต่อไปนี้ (พบได้ที่นี่ในAutoMapperExtensionsคลาส):

// from http://stackoverflow.com/questions/954480/automapper-ignore-the-rest/6474397#6474397
public static IMappingExpression IgnoreAllNonExisting(this IMappingExpression expression)
{
    foreach(var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

สิ่งสำคัญคือเมื่อสแตติก API ถูกลบแล้วโค้ดเช่นMapper.FindTypeMapForจะไม่ทำงานอีกต่อไปดังนั้นการใช้expression.TypeMapฟิลด์


7
ตั้งแต่ 5.0 expression.TypeMapไม่มีให้บริการแล้ว นี่คือทางออกของฉันสำหรับ 5.0
Richard

ฉันต้องใช้public static IMappingExpression<TSource, TDestination> IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)เพื่อแก้ไขปัญหาประเภท
Nick M

16

สำหรับ Automapper 5.0 เพื่อข้ามคุณสมบัติที่ไม่ได้แมปทั้งหมดที่คุณต้องการ

.ForAllOtherMembers (x => x.Ignore ());

ในตอนท้ายของโปรไฟล์ของคุณ

ตัวอย่างเช่น:

internal class AccountInfoEntityToAccountDtoProfile : Profile
{
    public AccountInfoEntityToAccountDtoProfile()
    {
        CreateMap<AccountInfoEntity, AccountDto>()
           .ForMember(d => d.Id, e => e.MapFrom(s => s.BankAcctInfo.BankAcctFrom.AcctId))
           .ForAllOtherMembers(x=>x.Ignore());
    }
}

ในกรณีนี้เฉพาะฟิลด์ Id สำหรับวัตถุที่ส่งออกจะได้รับการแก้ไขอื่น ๆ ทั้งหมดจะถูกข้าม ทำงานเหมือนมีเสน่ห์ดูเหมือนว่าเราไม่ต้องการส่วนขยายที่ยุ่งยากอีกต่อไป!


10

ฉันได้อัปเดตคำตอบของ Robert Schroeder สำหรับ AutoMapper 4.2 ด้วยการกำหนดค่า mapper แบบคงที่เราไม่สามารถใช้Mapper.GetAllTypeMaps()แต่expressionมีการอ้างอิงถึงสิ่งที่ต้องการTypeMap:

public static IMappingExpression<TSource, TDestination> 
    IgnoreAllNonExisting<TSource, TDestination>(this IMappingExpression<TSource, TDestination> expression)
{
    foreach (var property in expression.TypeMap.GetUnmappedPropertyNames())
    {
        expression.ForMember(property, opt => opt.Ignore());
    }
    return expression;
}

ไม่ทำงานใน AutoMapper 5.0 คุณสมบัติ .TypeMap บน IMappingExpression ไม่พร้อมใช้งาน สำหรับรุ่น 5. ดูส่วนขยายในคำตอบของ Richard
Michael Freidgeim

ทำงานร่วมกับ AM 4.2
Leszek P

8

คุณต้องการระบุให้สมาชิกบางคนถูกเพิกเฉยอย่างไร มีการประชุมหรือคลาสพื้นฐานหรือแอตทริบิวต์ที่คุณต้องการสมัครหรือไม่? เมื่อคุณเข้าสู่ธุรกิจของการระบุการแมปทั้งหมดอย่างชัดเจนแล้วฉันไม่แน่ใจว่ามูลค่าที่คุณจะได้รับจาก AutoMapper


จิมมี่คุณมีประเด็นเกี่ยวกับความชัดเจน สำหรับวิธีการบรรลุเป้าหมายนี้อย่างสง่างามที่สุด: คลาสฐานและคุณลักษณะจะไม่ทำงานในสถานการณ์นี้เนื่องจากคลาสเป้าหมายไม่ได้อยู่ภายใต้การควบคุมของฉัน - พวกเขาถูกสร้างขึ้นโดยอัตโนมัติจากสัญญาข้อมูล XSD ดังนั้นหนึ่งจะมี เพื่อแก้ไขรหัสนี้ด้วยตนเองหลังจากแต่ละรอบการสร้าง ฉันเดาทางออกขึ้นอยู่กับกรณีที่เป็นรูปธรรม บางทีอินเทอร์เฟซที่คล่องแคล่วคล้ายกับปราสาทวินเซอร์แห่งหนึ่งที่มีให้สำหรับการเลือกส่วนประกอบที่จะลงทะเบียนในคอนเทนเนอร์อาจเป็นวิธีแก้ปัญหาได้หรือไม่
Igor Brejc

อ่ามันสมเหตุสมผลมากกว่านี้แล้ว นั่นเป็นคุณสมบัติที่น่าสนใจฉันจะดูหนึ่งในช่วงเวลา 2.1
Jimmy Bogard

2
เพียงแค่มีค่าที่สามารถกำหนดค่าได้ซึ่งคุณสามารถ "ละเว้น" ฟิลด์ที่ไม่มีอยู่ทั้งหมดได้
Ricardo Sanchez

6
นี่ไม่ใช่คำตอบสำหรับคำถาม
2864740

สวัสดีจิมมี่คุณเป็นผู้เขียนใช่ไหม? ฉันต้องการที่จะเพิกเฉยต่อคุณสมบัติที่ไม่ได้มีอยู่ทั้งหมดซึ่งเป็นพฤติกรรมเริ่มต้น (อาจถูกควบคุมโดยการตั้งค่าสถานะ) นอกจากนี้ฉันยังพบข้อผิดพลาดแปลก ๆ จาก AutoMapper ที่ฉันไม่สามารถเข้าใจได้ มันไม่ได้ให้อะไรพิเศษกับฉันเลย
นาโอมิ

7

นี่ดูเหมือนเป็นคำถามเก่า แต่คิดว่าฉันจะโพสต์คำตอบสำหรับคนอื่นที่ดูเหมือนว่าฉันเป็น

ฉันใช้ ConstructU การใช้วัตถุเริ่มต้นพร้อมกับ ForAllMembers ละเว้นเช่น

    Mapper.CreateMap<Source, Target>()
        .ConstructUsing(
            f =>
                new Target
                    {
                        PropVal1 = f.PropVal1,
                        PropObj2 = Map<PropObj2Class>(f.PropObj2),
                        PropVal4 = f.PropVal4
                    })
        .ForAllMembers(a => a.Ignore());

1

กลุ่มข้อมูลข่าวสารเพียงประมาณละเลยสมาชิกหลายคนเป็นหัวข้อนี้ - http://groups.google.com/group/automapper-users/browse_thread/thread/9928ce9f2ffa641f ฉันคิดว่าคุณสามารถใช้เคล็ดลับที่ใช้ใน ProvidingCommonBaseClassConfiguration เพื่อละเว้นคุณสมบัติทั่วไปสำหรับคลาสที่คล้ายกัน
และไม่มีข้อมูลเกี่ยวกับฟังก์ชัน "ละเว้นส่วนที่เหลือ" ฉันเคยดูโค้ดมาก่อนและดูเหมือนว่าสำหรับฉันจะเพิ่มฟังก์ชั่นดังกล่าวได้ยากมาก นอกจากนี้คุณสามารถลองใช้แอททริบิวและทำเครื่องหมายด้วยมันละเว้นคุณสมบัติและเพิ่มรหัสทั่วไป / ทั่วไปเพื่อละเว้นคุณสมบัติที่ทำเครื่องหมายไว้ทั้งหมด


1
บางทีวิธีหนึ่งอาจจะใช้วิธี ForAllMembers และใช้ IMemberConfigurationExpression ของฉันเองซึ่งได้รับสตริงที่มีชื่อคุณสมบัติของคุณสมบัติเหล่านั้นซึ่งไม่ควรละเว้นและผ่านส่วนที่เหลือแล้วโทร Ignore () แค่ความคิดฉันไม่แน่ใจว่ามันจะได้ผลหรือไม่
Igor Brejc

ใช่มันสามารถใช้งานได้เช่นกัน แต่วิธีนี้มีความยุ่งยากมากกว่าการใช้แอตทริบิวต์ แต่ให้ความยืดหยุ่นมากกว่า เป็นเรื่องน่าเสียดายที่ไม่มีกระสุนเงิน :(.
zihotki

1

ฉันรู้ว่านี่เป็นคำถามเก่า แต่ @jmoerdyk ในคำถามของคุณ:

คุณจะใช้มันอย่างไรในนิพจน์ CreateMap () ที่ถูกล่ามโซ่ในโปรไฟล์?

คุณสามารถใช้คำตอบนี้เช่นนี้ภายใน ctor รายละเอียด

this.IgnoreUnmapped();
CreateMap<TSource, Tdestination>(MemberList.Destination)
.ForMember(dest => dest.SomeProp, opt => opt.MapFrom(src => src.OtherProp));

0

คุณสามารถใช้ ForAllMembers ได้แทนที่จะเขียนทับแบบนี้เท่านั้น

public static IMappingExpression<TSource, TDest> IgnoreAll<TSource, TDest>(this IMappingExpression<TSource, TDest> expression)
        {
            expression.ForAllMembers(opt => opt.Ignore());
            return expression;
        }

ระวังมันจะไม่สนใจทั้งหมดและถ้าคุณจะไม่เพิ่มการแมปที่กำหนดเองพวกเขาจะถูกละเว้นแล้วและจะไม่ทำงาน

นอกจากนี้ฉันอยากจะบอกว่าถ้าคุณมีการทดสอบหน่วยสำหรับ AutoMapper และคุณทดสอบว่าทุกรุ่นที่มีการแมปคุณสมบัติทั้งหมดอย่างถูกต้องคุณไม่ควรใช้วิธีการขยายดังกล่าว

คุณควรเขียนความไม่สนใจอย่างชัดเจน


-1

โซลูชันปัจจุบัน (เวอร์ชัน 9) สำหรับการเพิกเฉยต่อคุณสมบัติที่ไม่มีอยู่ในประเภทปลายทางคือการสร้างการแมปแบบพลิกแล้วย้อนกลับ:

var config = new MapperConfiguration(cfg => {
  cfg.CreateMap<TheActualDestinationType, TheActualSourceType>().ReverseMap();
});

-2

ในเวอร์ชั่น 3.3.1 คุณสามารถใช้IgnoreAllPropertiesWithAnInaccessibleSetter()หรือIgnoreAllSourcePropertiesWithAnInaccessibleSetter()วิธีการ


6
สิ่งนี้ใช้ไม่ได้กับคำถามของผู้โพสต์ดั้งเดิม วิธีการเหล่านี้จะละเว้นคุณสมบัติที่ได้รับการป้องกันหรือเป็นส่วนตัวไม่ใช่คุณสมบัติที่หายไปจากแหล่งที่มา แต่มีอยู่ในประเภทปลายทาง
ด่าน
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.