0条留言

Xamarin的图标 & 手机中的自动映射器

您可能已经听说过 自动贴图 ,该库可帮助您将“属性表单”对象复制到由编写的另一个 吉米·博加德(Jimmy Bogard) 。每当您创建更大的Xamarin Forms应用程序时,通常都会得到代表相似数据但针对应用程序不同区域的不同模型。例如,您将从后端获得一个极简的数据传输对象(DTO),您可以将其复制到另一个应用程序内部模型中,或直接复制到表示视图中显示的数据的视图模型中。这就是AutoMapper可以帮助您并阻止您编写所有复制代码的地方。

我必须承认-一开始它总是有点像过分杀伤。在项目结束时,我仍然很高兴在开始时就做出了决定。因此,让我们看看如何开始。

进行设定

设置很简单,实际上添加了 NuGet包 of 自动贴图 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 自动贴图 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 自动贴图 . 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属性窗格

配置和用法

好的,现在一切都已设置好,我们仍然必须告诉AutoMapper我们要将哪些对象从A复制到B并再次返回。在为这篇博客准备的小应用程序中,我们将把笔记DTO对象复制到它的View Model对应对象中。因此,要获取配置的AutoMapper实例,我们将在应用程序启动期间编写如下代码:

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

    return mapperConfiguration.CreateMapper();
}jjjjjjj

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

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

But what I often end up doing is populating the View Model after creation 要么 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 自动贴图 to map the DTO directly on the View Model itself:

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

如果您有一个视图模型列表,即 集合视图 要么 列表显示 ,我们将使用 LINQ 与AutoMapper结合使用,可以从DTO快速转换为View Model:

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 自动贴图 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.

  自动贴图 配置测试失败的屏幕截图

那项测试已将我从那么多被遗忘的数据字段中解救了出来-我想说的是它拯救了我的一个朋友... ðŸ〜 ...

往回看

我肯定会在以后的Xamarin Forms项目中使用AutoMapper,因为它们不仅方便复制属性,而且还具有DTO,内部模型和视图模型的共享。但这也使我免于忘记为对象添加属性。

请务必查看官方 文件资料 因为这篇文章几乎没有涉及您可以使用AutoMapper配置的内容。

与往常一样,您可以在上找到完整的小样本应用程序 的GitHub .

高温超导