C#でAutoMapperを使って別DTOをコピーする

# 1. はじめに
* WebAPIを使用するとModelとEntityが同じような内容になるのでC#で使えるMapperでコピーしたい
* 起動時にMapperの設定をまとめて書けるようにしたい

# 2. 開発環境
* C#
* Visual Studio 2022
* AutoMapper 12.0.1 (NuGet)

# 3. AutoMapperの取得
* NuGetpパッケージの管理から```AutoMapper```をインストールする
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/0eb27afe-d0ed-8cdc-9ff4-6d8988e7c6d0.png)

# 4. AutoMapperの使用方法
## 4.1. 単純にマッピングする
* Book1からBook2へマッピングする
```csharp
public class Book1 { public int ID { get; set; } }        
public class Book2 { public int ID { get; set; } }

private void Form1_Load(object sender, EventArgs e)
{
    // テストデータ作成
    List<Book1> book1 = new List<Book1>();
    Book1 book11 = new Book1();
    book11.ID = 1;
    book1.Add(book11);
    Book1 book12 = new Book1();
    book12.ID = 2;
    book1.Add(book12);

    // 単純にbook1 → book2にマッピング
    var config = new MapperConfiguration(cfg => cfg.CreateMap<Book1, Book2>());
    var mapper = new Mapper(config);
    List<Book2> book2 = mapper.Map<List<Book2>>(book1);

    // デバッグ用
    book2.ForEach(x => Debug.Print(x.ID.ToString()));
}
```

* 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/495fef96-5c1f-d113-9909-9f5fd747103c.png)

## 4.2. 値を除外する
* IDの項目をマッピングから除外する
* Ignoreメソッドを使用する
```csharp
    // book1 → book2にマッピング(IDを除外)
    var config = new MapperConfiguration(cfg => cfg.CreateMap<Book1, Book2>()
        .ForMember(book1 => book1.ID,
        option => option.Ignore())
    );
```

* 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/176ca5ac-b96f-6d4d-2965-00a3806bfe70.png)

## 4.3. 値を編集する
* IDの値を2倍に編集する
* MapFromメソッドを使用する
```csharp
    // book1 → book2にマッピング(IDの値を2倍に編集)
    var config = new MapperConfiguration(cfg => cfg.CreateMap<Book1, Book2>()
        .ForMember(book1 => book1.ID,
        option => option.MapFrom(x => x.ID * 2))
    );
```

* 実行結果
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2852081/761fb71a-8f1a-e352-b1b8-d5a6c2bf9ee7.png)

## 4.4. 型違いをコピーする
* 試しにBook1のintのID → Book2のstringのIDへコピーする
* 型が違っても上記のプロパティが同じであれば同じマッピング設定でコピーできている
```csharp
    public class Book1 { public int ID { get; set; } }        
    public class Book2 { public string ID { get; set; } }

    // 単純にbook1 → book2にマッピング (4.1.と同じ)
    var config = new MapperConfiguration(cfg => cfg.CreateMap<Book1, Book2>());
    var mapper = new Mapper(config);
    List<Book2> book2 = mapper.Map<List<Book2>>(book1);
```


# 5. AutoMapperの起動時設定
## 5.1. Profileの作成
* AutoMapperのProfieクラスを継承してマッピング設定をまとめて書く
```csharp:UserProfile
using AutoMapper;
public class UserProfile:Profile
{
    public UserProfile()
    {
        // マッピング設定をまとめて書く
        CreateMap<Book1, Book2>()
            .ForMember(book2 => book2.ID,   // IDを編集する
            option => option.MapFrom(x => x.ID*2));
    }
}
```
## 5.2. Profileの読み込み（起動時）
* 起動時にまとめてProfileを読み込む
```csharp
private void Form1_Load(object sender, EventArgs e)
{
    // テストデータ作成
    // (省略)

    // マッピング設定を読み込む
    var mapperConfig = new MapperConfiguration(mc =>
    {
        mc.AddProfile(new UserProfile());
    });
    IMapper mapper = mapperConfig.CreateMapper();

    // マッピングをする
    List<Book2> book2 = mapper.Map<List<Book2>>(book1);

    // デバッグ用
    book2.ForEach(x => Debug.Print(x.ID.ToString()));
}
```

# 6. 参考文献
https://github.com/AutoMapper/AutoMapper

https://qiita.com/belre/items/fec14e57935015fbe674