在Xamarin中使用automapper表格应用程序

Xamarin的图标&在手机中的汽车

你可能已经听说过 自动分析器,该库可帮助您将属性复制到另一个人写入的另一个 吉马·蒙德。每当您创建较大的XAMARIN表单应用程序时,您通常最终结束,表示类似数据的不同模型,但对于应用程序的不同区域。例如,您将从后端获取一个简单的数据传输对象(DTO),您可能会将其复制到另一个应用程序内部模型中,或者直接转到表示在视图上显示的数据的视图模型。这是Automapper将帮助您和阻止您写入所有复制代码的地方。

我必须承认 - 虽然一开始就觉得一直感觉有点像矫枉过正。在项目结束时,我仍然很高兴在开始时做出决定。所以让我们看看我们是如何开始的。

获取设置

建立非常直,实际上是添加的 尼古特包 of AutoMapper to your Xamarin Forms project. That is until you start compiling for iOS, then it will all blow up due to some reflection issue. Since iOS is compiled Ahead Of Time (AOT), you can’t do any runtime operations such as reflections. Now AutoMapper does not use reflection when running on iOS. Still, due to some weird compilation thingy issue - I haven’t understood the point in detail - the compiler ends up trying to add reflection which will not work on iOS. So to make things run under iOS, we have to add the following line to our iOS csproj file:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
  ...
  <ItemGroup>
    ...
    <PackageReference Include="System.Reflection.Emit" Version="4.7.0">
      <ExcludeAssets>all</ExcludeAssets>
      <IncludeAssets>none</IncludeAssets>
    </PackageReference>
  </ItemGroup>
  ...
</Project>

Then there is still the Linker under iOS that tries to remove the System.Convert assembly. Which is required by AutoMapper. But luckily we can help the linker out here by adding an XML file:

<linker>
  <assembly fullname="mscorlib">
    <type fullname="System.Convert" preserve="All" />
  </assembly>
</linker>

And setting the build property to LinkDescription:

显示Visual Studio Properties Pane

配置和用法

好的,所以现在一切都已设置,我们仍然必须告诉automapper我们想从a到b再次复制哪些对象。在我为此博客准备的小型应用程序中,我们会将Note DTO对象复制到它的视图模型对象。因此要获取已配置的automapper实例,我们将在应用程序启动期间写下类似的内容:

public static IMapper CreateMapper()
{
    var mapperConfiguration = new MapperConfiguration(cfg =>
    {
        cfg.CreateMap<Note, NoteViewModel>();
        cfg.CreateMap<NoteViewModel, Note>();
    });

    return mapperConfiguration.CreateMapper();
}jjjjjjj

现在,我们可以通过调用automapper实例如下调用automapper实例将dto转换为视图模型:

var viewModel = _mapper.Map<MainViewModel>(note);

But what I often end up doing is populating the View Model after creation or when the Page/View it is being used in is getting created. For example, an Init method on the View Model might be invoked during the OnAppearing of the View. Then we could call a service in the View Model which would return a DTO of that object. In this scenario, we will want to tell AutoMapper to map the DTO directly on the View Model itself:

public async void Init()
{
    var note = (await _noteService.GetNotes()).First();
    _mapper.Map(note, this);
}

如果您有一个视图模型列表,即a CollectionView. 或者 列表显示,我们会使用 LINQ. 与Automapper结合使用,以便从DTO开始转换以查看模型:

Notes = (await _noteService.GetNotes())
            .Select(_mapper.Map<MainViewModel>)
            .ToList();

只要必须在您的应用程序中呈现新的DTO,就会让Automapper放置在您的应用程序中,您将添加新配置,然后能够使用映射。因此,您需要的映射越多,Automapper的更快就会自动支付。

但是,在我的项目中使用automapper时,我真的很喜欢一件事,这是测试。

测试您的映射

“测试?你是认真的?” - 好吧,我其实是我。您可以使用简单的测试用例检查您的配置:

[Fact]
public void AppBoostrapper_ValidateMapping_AssertCorrectness()
{
    var mapper = AppBootstrapper.CreateMapper();
    mapper.ConfigurationProvider.AssertConfigurationIsValid();
}

This test will tell you if AutoMapper has all the information necessary to copy your data from one object to the other. So if we start adding Commands to the View Model, the mapping will fail with the information that it can not map the command into our DTO. And we obviously do not want to send an ICommand data field back to the server, so we ignore it:

cfg.CreateMap<Note, NoteViewModel>()
    .ForMember(n => n.ExecuteReset, opt => opt.Ignore())
    .ForMember(n => n.ExecuteStore, opt => opt.Ignore());
cfg.CreateMap<NoteViewModel, Note>();

But what when we add a data field WriterMood to the DTO and forget to add it to the View Model? Correct, the test will fail and inform us that we have forgotten to add the field.

Failed Automapper Config Test的屏幕截图

那个测试已经从这么多忘记的数据字段中保存了我 - 我的意思是说它拯救了我的朋友...... -

往后看

我肯定会在我未来的XAMarin表单项目中使用Automapper,这些项目具有他们的DTO,内部模型和视图模型,因为它不仅可以方便复制属性。但它还可以忘记为对象添加属性。

一定要查看官方 文件 自从这篇文章勉强划伤了您可以使用automapper配置的。

一如既往,您可以找到完整的小样本应用程序 GitHub..

Hth.

Updated: