2012-05-22 7 views
8

AutoMapperは、特定のマッピングを一時的に中断するために "説得力"を持たせることができますか?AutoMapperは、特定のマッピングを一時的に中断するために "説得"できますか?

達成しようとしていることを説明するために、私はイラストを使用します。学生、コース、アクティビティ、クラブなどのデータベースオブジェクト(テーブル)と対話するためにLINQを使用するリポジトリStudentRepositoryがあるとします。アプリケーション側では、一致するドメインオブジェクトStudent、Course、Activity、Clubがあります。 Studentクラスのようなアレイ型コース、活動のメンバー、クラブが含ま:

public class Student 
{ 
    // ... more members 
    public Course[] Courses { get; set; } 
    public Activity[] Activities { get; set; } 
    public Club[] Clubs { get; set; } 
    // ... even more members 
} 

AutoMapperはマッピングのようなStudentRepositoryの静的コンストラクタで定義されているドメイン・オブジェクトへのデータベース・オブジェクトにマップするように構成されている。

public class StudentRepository : IStudentRepository 
{ 
    static class StudentRepository 
    { 
     // ... other mappings 

     Mapper.CreateMap<TableStudent, Student>() 
      .ForMember(dest => dest.Courses, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Course>>(src.TableCourses))) 
      .ForMember(dest => dest.Activities, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Activity>>(src.TableActivities))) 
      .ForMember(dest => dest.Clubs, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Clubs>>(src.TableClubs))) 
     // where TableStudents, TableCourses, TableActivities, TableClubs are database entities 

     // ... yet more mappings 

    } 
} 

AutoMapperが1つのファンクションブロック内でマッピングをサスペンドするように説得することは可能ですか?

public Student[] GetStudents() 
{ 
    DataContext dbContext = new StudentDBContext(); 

    var query = dbContext.Students; 
    // => SUSPEND CONFIGURATION MAPPINGS for Subjects, Activities and Clubs WHILE STILL making use of others 
    // => The idea here it to take personal charge of 'manually' setting the particular members (*for some specific reasons) 

    var students = Mapper.Map<Student>(query); // => Still be able to use AutoMapper to map other members 
} 

public Student[] OtherStudentRepositoryMethods() 
{ 
    // Other repository methods continue to make use of the mappings configured in the static constructor 
} 

NOTE「いくつかの特別な理由ため」:1が1の場合、このhttp://codebetter.com/davidhayden/2007/08/06/linq-to-sql-query-tuning-appears-to-break-down-in-more-advanced-scenarios/どこだろう離れAutoMapperからの制御をしたいことがあり一つの理由:例えば、N団体、LINQ SQLへクエリごとに1:1の関連付けを結合することのみをサポートします。 AutoMapperはここでは非効率的です - N人の生徒のコースをロードするためにN回の呼び出しを行い、同じN人の生徒のアクティビティをロードするためのN個のコールが返されます。

+0

私はこれを試したことはありませんが、「BeforeMap」 'Mapper.CreateMap ()。BeforeMap(x => {Mapper.CreateMap ()。ForMember ...}) '前のマップで地図を作成します。マップを何度も再作成しないようにするための追加のチェックがあるかもしれません。 –

答えて

4

AutoMapperが1つのファンクションブロック内でマッピングをサスペンドするように説得することはできますか?

私が知っているように、それを行うための最善の方法 - (無視使用)この

public class StudentRepository : IStudentRepository 
{ 
    static class StudentRepository 
    { 
     // ... other mappings 

     Mapper.CreateMap<TableStudent, Student>() 
      .ForMember(dest => dest.Courses, opt => opt.Ignore()) 
      .ForMember(dest => dest.Activities, opt => opt.Ignore()) 
      .ForMember(dest => dest.Clubs, opt => opt.Ignore()) 
     // where TableStudents, TableCourses, TableActivities, TableClubs are database entities 

     // ... yet more mappings 

    } 
} 

のような、それが前に気づいたとしても、私はそれぞれの目標のために異なるプロファイルを使用することをお勧めいたしますたいですあなたが達成したい。

public BaseService() 
{ 
    AutoMapperRegistry.Configure(); 
} 

public class AutoMapperRegistry 
{ 
    public static void Configure() 
    { 
     Mapper.Initialize(x => 
     { 
      x.AddProfile<ServiceProfile1>(); 
      x.AddProfile<ServiceProfileReverseProfile1>(); 
     }); 
    } 
} 

public class ServiceProfile1 : Profile 
{ 
    protected override string ProfileName 
    { 
     get 
     { 
      return "ServiceProfile1"; 
     } 
    } 

    protected override void Configure() 
    { 
     Mapper.CreateMap<DataContract_Sub, DTO_Sub>(); 
     Mapper.CreateMap<DataContract, DTO>() 
      .ForMember(x => x.DataContract_Sub, opt => opt.MapFrom(y => y.DTO_Sub)) 
    .BeforeMap((s, d) => 
      { 
       // your custom logic 
      }) 
    .AfterMap((s, d) => 
      { 
       // your custom logic 
      }); 
    } 
} 
+0

これは回避策のようです。消化する... –

2

これを達成する方法の1つは、シナリオごとに別々のマッピングエンジンインスタンスを作成することです。ジミーボガードのthis answerで示唆されているように、別のマップを構成できます。

0

hmm ...フィードバックの方々ありがとうございます。私はすべての答えと提案を検討する時間がかかりました。彼らは思考のための多くの食糧を提供しましたが、特に正確にはうまくいきません。私は何かを注入する必要があると思った。 (免責事項:私の意見は、その汚いアプローチ - 多くのことが間違っている可能性があり、マーフィーの法律は保持し続けているということです)。特定のインスタンスのIgnore機能を活用して、マッピングを「サスペンド」することができます。通常、try&catchブロックでは次のようになります。

public Student[] GetStudents() 
{ 
    try 
    { // Suspend/Ignore the mappings 
     // => SUSPEND CONFIGURATION MAPPINGS for Subjects, Activities and Clubs 
     Mapper.CreateMap<TableStudent, Student>() 
        .ForMember(dest => dest.Courses, opt => opt.Ignore()) 
        .ForMember(dest => dest.Activities, opt => opt.Ignore()) 
        .ForMember(dest => dest.Clubs, opt => opt.Ignore()) 

     DataContext dbContext = new StudentDBContext(); 

     var query = dbContext.Students; 

     // other logic ... 

     var students = Mapper.Map<Student>(query); // => Still be able to use AutoMapper to map other members 
     // set the properties you needed to do manually 
    } 
    finally // Restore back the mappings 
    { 
     Mapper.CreateMap<TableStudent, Student>() 
        .ForMember(dest => dest.Courses, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Course>>(src.TableCourses))) 
        .ForMember(dest => dest.Activities, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Activity>>(src.TableActivities))) 
        .ForMember(dest => dest.Clubs, opt => opt.MapFrom(src => Mapper.Map<IEnumerable<Clubs>>(src.TableClubs))) 
    } 
} 

私が言及したように、おそらく汚れています。最終的にブロック内でCreateMap()が失敗した場合でも、アプローチをオーバーホールすることができなかったレガシーアプリケーションでは、どんな種類の例外的な状況が発生する可能性があるか分からないので、私はうれしいでしょう。上記の@AndriyZakharkoで提案されたような異なるプロファイルを使用する可能性があります。一時的に制御を取り戻すために使用できます。私は個人的に試しました。

関連する問題