2010-04-29 34 views
10

Gọi tất cả các chuyên gia AutoMapper!AutoMapper Làm thế nào để ánh xạ đối tượng A đến đối tượng B khác nhau Tùy thuộc vào ngữ cảnh

Tôi muốn có thể ánh xạ đối tượng A để đối tượng B khác nhau tùy thuộc vào ngữ cảnh khi chạy. Đặc biệt, tôi muốn bỏ qua các thuộc tính nhất định trong một trường hợp ánh xạ và có tất cả các thuộc tính được ánh xạ trong một trường hợp khác.

Điều tôi đang gặp là Mapper.CreateMap có thể được gọi thành công trong các trường hợp ánh xạ khác nhau, khi CreateMap được gọi, bản đồ cho một cặp loại cụ thể được đặt và sau đó không thay đổi. có thể mô tả ánh xạ khác nhau.

Tôi tìm thấy một bài đăng trên blog ủng hộ Mapper.Reset() để giải quyết vấn đề, tuy nhiên, tính chất tĩnh của lớp Mapper có nghĩa là nó chỉ là vấn đề thời gian trước khi xảy ra va chạm và va chạm.

Có cách nào để thực hiện việc này không?

Điều tôi nghĩ tôi cần là gọi Mapper.CreateMap một lần cho mỗi tên miền ứng dụng và sau đó, có thể gọi Mapper.Map với các gợi ý về những thuộc tính nào nên được bao gồm/loại trừ.

Ngay bây giờ, tôi đang suy nghĩ về việc thay đổi mã nguồn bằng cách viết một lớp ánh xạ không tĩnh giữ bản sao cấu hình ánh xạ. Hiệu suất kém, nhưng chủ đề an toàn.

Tùy chọn của tôi là gì. Những gì có thể được thực hiện? Automapper có vẻ rất hứa hẹn.

+2

@Omu: Bạn và "ValueInjecter" của bạn đang bắt đầu rất khó chịu. Bạn không phải trả lời mỗi câu hỏi AutoMapper với plugin của bạn cho ValueInjecter (nó không phải là ValueInjector). Cá nhân tôi bị tắt bởi điều này, và thậm chí sẽ không nhìn nó do chiến thuật của bạn. Nó không chỉ là người chuyên nghiệp. – epitka

Trả lời

5

Lớp Mapper chỉ đơn thuần là một trình bao bọc mỏng trên đầu các đối tượng Cấu hình và Ánh xạ. Bạn có thể tạo các cá thể riêng biệt của các đối tượng Configuration/MappingEngine (vẫn còn sử dụng các singletons), và sử dụng container IoC của bạn để chọn đúng đối tượng cần thiết.

Tùy chọn tốt nhất vẫn là sử dụng các loại đích khác nhau. Phần thực sự khó khăn về thực sự hỗ trợ tính năng này là bản chất phân cấp vốn có của bản đồ kiểu. Đối tượng cấp cao nhất có thể có một lược đồ ánh xạ, trong khi các đối tượng cấp thấp hơn thì không. Một số ở giữa có thể có nó hay không vv

1

Đối với tôi, nó có vẻ giống như một thiết kế tốt hơn có thể có nhiều lớp đích (có thể kế thừa từ một cơ sở chung hoặc thực hiện một giao diện chung)

Nếu Các thuộc tính chưa được ánh xạ sẽ không bao giờ được sử dụng trong một trong các biến thể, bạn có thể để chúng hoàn toàn (cho phép biên dịch thời gian đảm bảo rằng chúng không được sử dụng do nhầm lẫn), ném một ngoại lệ khi chúng được truy cập (không tốt như thời gian biên dịch, nhưng đôi khi bạn cần giao diện đầy đủ để được triển khai) hoặc thậm chí sử dụng giá trị thay thế.

Ví dụ:

public class Source 
{ 
    public string Name {get;set;} 
    public BigEntity {get;set;} 

    /* other members */ 
} 

public class SourceDTO 
{ 
    public string Name {get;set;} 
    public BigEntity {get;set;} 
} 

public class SourceSummaryDTO 
{ 
    public string Name {get;set;} 
} 

Ngoài ra, bạn có thể làm điều này:

public class SourceSummaryDTO : SourceDTO 
{ 
    public string Name {get;set;} 
    public BigEntity 
    { 
     get{throw new NotSupportedException();} 
     set{throw new NotSupportedException();} 
    } 
} 

Bằng cách đó, bạn có thể vượt qua một SourceSummaryDTO như thể nó là một SourceDTO.

Có các thuộc tính có âm thanh có điều kiện như công thức gây rắc rối cho tôi - tôi muốn có các lớp rõ ràng về những gì chúng chứa, đặc biệt là với các đối tượng Chuyển dữ liệu.

Đối với tôi, điều tốt nhất về Automapper là khả năng xác minh ánh xạ và sau đó biết rằng mọi thuộc tính trên các lớp đích sẽ được điền.

13

Chỉ cần để bổ sung cho câu trả lời của Jimmy đây là mã cần thiết để sử dụng mà không có sự AutoMapper Mapper tĩnh

Tính đến phiên bản 4.2.1 Automapper có một ánh xạ tĩnh không bị xử phạt và cấu hình (nhờ Jimmy!).

var config = new MapperConfiguration(cfg => { 
    cfg.CreateMap<ClassA, ClassB>(); 
}); 

var mapper = config.CreateMapper(); 

Có nhiều tùy chọn hữu ích khác (chẳng hạn như tiểu sử) trong bản phát hành mới để tạo các phiên bản bản đồ khác nhau. Bạn có thể nhận được tất cả các chi tiết trong official documentation

(chính xác cho phiên bản 4.1.1)

// Configuration 
AutoMapper.Mappers.MapperRegistry.Reset(); 
var autoMapperCfg = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers); 
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg); 
autoMapperCfg.Seal(); 

//Usage example 
autoMapperCfg.CreateMap<ClassA, ClassB>(); 

var b = mappingEngine.Map<ClassB>(a); 

(chính xác cho phiên bản 3.2.1)

// Configuration 
var platformSpecificRegistry = AutoMapper.Internal.PlatformAdapter.Resolve<IPlatformSpecificMapperRegistry>(); 
platformSpecificRegistry.Initialize(); 

var autoMapperCfg = new AutoMapper.ConfigurationStore(new TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.Mappers); 
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg); 

//Usage example 
autoMapperCfg.CreateMap<ClassA, ClassB>(); 

var b = mappingEngine.Map<ClassB>(a); 

(chính xác cho phiên bản 2.2.1)

// Configuration 
var autoMapperCfg = new AutoMapper.ConfigurationStore(new AutoMapper.TypeMapFactory(), AutoMapper.Mappers.MapperRegistry.AllMappers()); 
var mappingEngine = new AutoMapper.MappingEngine(autoMapperCfg); 

//Usage example 
autoMapperCfg.CreateMap<ClassA, ClassB>(); 

var b = mappingEngine.Map<ClassB>(a); 
Các vấn đề liên quan