私は.NETに比較的慣れていないので、「古い方法」を学ぶ代わりに.NET Coreに取り組むことにしました。AutoMapper for .NET Coreの設定に関する詳細な記事はこちらにありますが、初心者向けの簡単なチュートリアルはありますか?
私は.NETに比較的慣れていないので、「古い方法」を学ぶ代わりに.NET Coreに取り組むことにしました。AutoMapper for .NET Coreの設定に関する詳細な記事はこちらにありますが、初心者向けの簡単なチュートリアルはありますか?
回答:
私はそれを考え出した!詳細は次のとおりです。
NuGetを介してAutoMapper Dependency Injection Packageをソリューションに追加します。
マッピングプロファイルの新しいクラスを作成します。(メインソリューションディレクトリにクラスを作成しMappingProfile.cs
、次のコードを追加しました。)例としてUser
およびUserDto
オブジェクトを使用します。
public class MappingProfile : Profile {
public MappingProfile() {
// Add as many of these lines as you need to map your objects
CreateMap<User, UserDto>();
CreateMap<UserDto, User>();
}
}
次に、Startup.cs
以下に示すようにAutoMapperConfigurationを追加します。
public void ConfigureServices(IServiceCollection services) {
// .... Ignore code before this
// Auto Mapper Configurations
var mappingConfig = new MapperConfiguration(mc =>
{
mc.AddProfile(new MappingProfile());
});
IMapper mapper = mappingConfig.CreateMapper();
services.AddSingleton(mapper);
services.AddMvc();
}
コード化されたオブジェクトをコードで呼び出すには、次のようにします。
public class UserController : Controller {
// Create a field to store the mapper object
private readonly IMapper _mapper;
// Assign the object in the constructor for dependency injection
public UserController(IMapper mapper) {
_mapper = mapper;
}
public async Task<IActionResult> Edit(string id) {
// Instantiate source object
// (Get it from the database or whatever your code calls for)
var user = await _context.Users
.SingleOrDefaultAsync(u => u.Id == id);
// Instantiate the mapped data transfer object
// using the mapper you stored in the private field.
// The type of the source object is the first type argument
// and the type of the destination is the second.
// Pass the source object you just instantiated above
// as the argument to the _mapper.Map<>() method.
var model = _mapper.Map<UserDto>(user);
// .... Do whatever you want after that!
}
}
これがASP.NET Coreで新しく始めるのに役立つことを願っています!.NETの世界にはまだ慣れていないので、フィードバックや批判は歓迎します。
Profile
クラスがどのように配置されているかを説明しています
ASP.NET CoreでAutoMapperを使用する手順。
手順1. NuGetパッケージからAutoMapper.Extensions.Microsoft.DependencyInjectionをインストールします。
ステップ2.「マッピング」という名前のマッピングを保持するために、ソリューションにフォルダーを作成します。
ステップ3. Mappingフォルダーを追加した後、「MappingProfile」という名前のクラスを追加しました。この名前は、一意でわかりやすい名前にすることができます。
このクラスでは、すべてのマッピングを維持します。
ステップ4.スタートアップ「ConfigureServices」でマッパーを初期化する
スタートアップクラスでは、作成したプロファイルを初期化し、AutoMapperサービスを登録する必要があります。
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
AutoMapperを初期化および登録する必要があるConfigureServicesメソッドを示すコードスニペット。
public class Startup
{
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public IConfiguration Configuration { get; }
public void ConfigureServices(IServiceCollection services)
{
services.Configure<CookiePolicyOptions>(options =>
{
// This lambda determines whether user consent for non-essential cookies is needed for a given request.
options.CheckConsentNeeded = context => true;
options.MinimumSameSitePolicy = SameSiteMode.None;
});
// Start Registering and Initializing AutoMapper
Mapper.Initialize(cfg => cfg.AddProfile<MappingProfile>());
services.AddAutoMapper();
// End Registering and Initializing AutoMapper
services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
}}
ステップ5.出力を取得します。
マップされた結果を取得するには、AutoMapper.Mapper.Mapを呼び出し、適切な宛先とソースを渡す必要があります。
AutoMapper.Mapper.Map<Destination>(source);
コードスニペット
[HttpPost]
public void Post([FromBody] SchemeMasterViewModel schemeMaster)
{
if (ModelState.IsValid)
{
var mappedresult = AutoMapper.Mapper.Map<SchemeMaster>(schemeMaster);
}
}
'Mapper' does not contain a definition for 'initialize'
。AutoMapper.Extensions.Microsoft.DependencyInjection
バージョン7.0.0 を使用しています
私は@theutzの答えを拡張したいと思います-つまりこの行
// services.AddAutoMapper(typeof(Startup)); // <-- newer automapper version uses this signature.
AutoMapper.Extensions.Microsoft.DependencyInjectionバージョン3.2.0にはバグ(おそらく)があります。(私は.NET Core 2.0を使用しています)
これは、この GitHubの問題で対処されています。AutoMapperのプロファイルクラスを継承するクラスが、スタートアップクラスであるアセンブリの外部に存在する場合、AutoMapperインジェクションが次のようになっていると、おそらく登録されません。
services.AddAutoMapper();
AutoMapperプロファイルを検索するアセンブリを明示的に指定しない限り。
Startup.ConfigureServicesで次のように実行できます。
services.AddAutoMapper(<assembies> or <type_in_assemblies>);
どこ「アセンブリ」と「type_in_assemblies」アプリケーション内のプロファイルのクラスが指定されているアセンブリをポイントします。例えば:
services.AddAutoMapper(typeof(ProfileInOtherAssembly), typeof(ProfileInYetAnotherAssembly));
私は仮定パラメータなしのオーバーロード(からソースコードの実装、次によること(と私は、この言葉に重点を置く)GitHubのを):
public static IServiceCollection AddAutoMapper(this IServiceCollection services)
{
return services.AddAutoMapper(null, AppDomain.CurrentDomain.GetAssemblies());
}
AutoMapperプロファイルが含まれているJIT済みのアセンブリがCLRに依存しています。AutoMapperプロファイルは必要な場合にのみjitされるため、trueまたはtrueでない場合があります(この StackOverflowの質問の詳細)。
ここでのtheutzの答えは非常に優れています。これを追加したいだけです。
のMapperConfigurationExpression
代わりにマッピングプロファイルを継承させる場合はProfile
、非常に簡単にテストを追加してマッピング設定を確認できます。これは常に便利です。
[Fact]
public void MappingProfile_VerifyMappings()
{
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(mappingProfile);
var mapper = new Mapper(config);
(mapper as IMapper).ConfigurationProvider.AssertConfigurationIsValid();
}
.NET Core 2.2 / Automapper 8.1.1 w / Extensions.DI 6.1.1の場合、この方法で解決しました(上記と同様ですが、よりクリーンなソリューションのように感じます)。
MappingProfile.csクラスを作成し、コンストラクターにマップを設定します(すべてのマッピングを保持するために単一のクラスを使用する予定です)
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Source, Dest>().ReverseMap();
}
}
Startup.csで、以下を追加してDIに追加します(アセンブリの引数は、マッピング構成を保持するクラス用です。私の場合は、MappingProfileクラスです)。
//add automapper DI
services.AddAutoMapper(typeof(MappingProfile));
コントローラーでは、他のDIオブジェクトと同じように使用します
[Route("api/[controller]")]
[ApiController]
public class AnyController : ControllerBase
{
private readonly IMapper _mapper;
public AnyController(IMapper mapper)
{
_mapper = mapper;
}
public IActionResult Get(int id)
{
var entity = repository.Get(id);
var dto = _mapper.Map<Dest>(entity);
return Ok(dto);
}
}
私のStartup.cs(Core 2.2、Automapper 8.1.1)
services.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
私のデータアクセスプロジェクト
namespace DAL
{
public class MapperProfile : Profile
{
// place holder for AddAutoMapper (to bring in the DAL assembly)
}
}
私のモデル定義では
namespace DAL.Models
{
public class PositionProfile : Profile
{
public PositionProfile()
{
CreateMap<Position, PositionDto_v1>();
}
}
public class Position
{
...
}
services.AddAutoMapper( typeof(DAL.MapperProfile) );
代わりに 使用しないのですservices.AddAutoMapper(new Type[] { typeof(DAL.MapperProfile) });
か?
私はたくさんの答え、特に@saineshwarの答えが好きです。AutoMapper 9.0で.net Core 3.0を使用しているので、答えを更新するときがきたと感じています。
私のために働いたのは、Startup.ConfigureServices(...)でこの方法でサービスを登録しました:
services.AddAutoMapper(cfg => cfg.AddProfile<MappingProfile>(),
AppDomain.CurrentDomain.GetAssemblies());
@saineshwarの残りの回答は完璧に保たれていると思います。しかし、誰かが興味を持っている場合、私のコントローラーコードは次のとおりです:
[HttpGet("{id}")]
public async Task<ActionResult> GetIic(int id)
{
// _context is a DB provider
var Iic = await _context.Find(id).ConfigureAwait(false);
if (Iic == null)
{
return NotFound();
}
var map = _mapper.Map<IicVM>(Iic);
return Ok(map);
}
そして私のマッピングクラス:
public class MappingProfile : Profile
{
public MappingProfile()
{
CreateMap<Iic, IicVM>()
.ForMember(dest => dest.DepartmentName, o => o.MapFrom(src => src.Department.Name))
.ForMember(dest => dest.PortfolioTypeName, o => o.MapFrom(src => src.PortfolioType.Name));
//.ReverseMap();
}
}
-----編集-----
Lucian Bargaoanuのコメントにリンクされているドキュメントを読んだ後、この回答を少し変更することをお勧めします。
パラメータservices.AddAutoMapper()
レス(@saineshwarの答えがあった)は(少なくとも私にとっては)機能しません。ただし、NuGetアセンブリAutoMapper.Extensions.Microsoft.DependencyInjectionを使用する場合、フレームワークはAutoMapper.Profileを拡張するすべてのクラス(mine、MappingProfileなど)を検査できます。
したがって、私の場合、クラスが同じ実行アセンブリに属している場合は、サービス登録を以下のように短縮できますservices.AddAutoMapper(System.Reflection.Assembly.GetExecutingAssembly());
(より洗練されたアプローチは、このコーディングでパラメーターのない拡張である可能性があります)。
ありがとう、ルシアン!
AutoMapper 6.1.1とasp.net Core 1.1.2を使用しています。
まず、Automapperのプロファイルクラスによって継承されるプロファイルクラスを定義します。空のIProfileインターフェイスを作成しました。このタイプのクラスを見つけることだけが目的です。
public class UserProfile : Profile, IProfile
{
public UserProfile()
{
CreateMap<User, UserModel>();
CreateMap<UserModel, User>();
}
}
次に、マッピングなどの別のクラスを作成します
public class Mappings
{
public static void RegisterMappings()
{
var all =
Assembly
.GetEntryAssembly()
.GetReferencedAssemblies()
.Select(Assembly.Load)
.SelectMany(x => x.DefinedTypes)
.Where(type => typeof(IProfile).GetTypeInfo().IsAssignableFrom(type.AsType()));
foreach (var ti in all)
{
var t = ti.AsType();
if (t.Equals(typeof(IProfile)))
{
Mapper.Initialize(cfg =>
{
cfg.AddProfiles(t); // Initialise each Profile classe
});
}
}
}
}
Startup.csファイルのMVC Core web Projectのコンストラクターで、アプリケーションのロード時にすべてのマッピングを初期化するMappingクラスを呼び出します。
Mappings.RegisterMappings();
ASP.NET Core(2.0+および3.0を使用してテスト済み)の場合、ソースドキュメントを読みたい場合:https : //github.com/AutoMapper/AutoMapper.Extensions.Microsoft.DependencyInjection/blob/master/README.md
それ以外の場合は、次の4つの手順に従ってください。
nugetからAutoMapper.Extensions.Microsoft.DependancyInjectionをインストールします。
いくつかのプロファイルクラスを追加するだけです。
次に、startup.csクラスに以下を追加します。
services.AddAutoMapper(OneOfYourProfileClassNamesHere)
次に、コントローラーまたは必要な場所にIMapperを挿入するだけです。
public class EmployeesController {
private readonly IMapper _mapper;
public EmployeesController(IMapper mapper){
_mapper = mapper;
}
そして、ProjectToを今すぐ使用したい場合は、次のようにします。
var customers = await dbContext.Customers.ProjectTo<CustomerDto>(_mapper.ConfigurationProvider).ToListAsync()
AutoMapper 9.0.0の場合:
public static IEnumerable<Type> GetAutoMapperProfilesFromAllAssemblies()
{
foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
{
foreach (var aType in assembly.GetTypes())
{
if (aType.IsClass && !aType.IsAbstract && aType.IsSubclassOf(typeof(Profile)))
yield return aType;
}
}
}
MapperProfile:
public class OrganizationProfile : Profile
{
public OrganizationProfile()
{
CreateMap<Foo, FooDto>();
// Use CreateMap... Etc.. here (Profile methods are the same as configuration methods)
}
}
あなたのスタートアップでは:
services.AddAutoMapper(GetAutoMapperProfilesFromAllAssemblies()
.ToArray());
コントローラーまたはサービス:マッパーを挿入:
private readonly IMapper _mapper;
使用法:
var obj = _mapper.Map<TDest>(sourceObject);
テストのためにArve Systadが述べたことに追加します。なんらかの理由で私のようであり、theutzソリューションで提供される継承構造を維持したい場合は、次のようにMapperConfigurationを設定できます。
var mappingProfile = new MappingProfile();
var config = new MapperConfiguration(cfg =>
{
cfg.AddProfile(mappingProfile);
});
var mapper = new Mapper(config);
これはNUnitで行いました。
services.AddAutoMapper(); うまくいきませんでした。(私はAsp.Net Core 2.0を使用しています)
以下のように設定した後
var config = new AutoMapper.MapperConfiguration(cfg =>
{
cfg.CreateMap<ClientCustomer, Models.Customer>();
});
マッパーを初期化しますIMapper mapper = config.CreateMapper();
マッパーオブジェクトをシングルトンサービスとしてサービスに追加します。AddSingleton(mapper);
このようにして、コントローラーにDIを追加できます
private IMapper autoMapper = null;
public VerifyController(IMapper mapper)
{
autoMapper = mapper;
}
そして、私は私の行動方法で以下のように使用しました
ClientCustomer customerObj = autoMapper.Map<ClientCustomer>(customer);
theutz answerについては、コントローラーコンストラクターでIMapperマッパーパラメーターを指定する必要はありません。
マッパーはコードの任意の場所で静的メンバーであるため、使用できます。
public class UserController : Controller {
public someMethod()
{
Mapper.Map<User, UserDto>(user);
}
}
IMapper
すると、それをモックして、たとえば、指定されたテストに関係がない場合はnullを返すようにすることができます。