使用 AutoMapper 展平嵌套对象的更好方法?
我一直在将域对象扁平化为 DTO,如下例所示:
public class Root
{
public string AParentProperty { get; set; }
public Nested TheNestedClass { get; set; }
}
public class Nested
{
public string ANestedProperty { get; set; }
}
public class Flattened
{
public string AParentProperty { get; set; }
public string ANestedProperty { get; set; }
}
// I put the equivalent of the following in a profile, configured at application start
// as suggested by others:
Mapper.CreateMap<Root, Flattened>()
.ForMember
(
dest => dest.ANestedProperty
, opt => opt.MapFrom(src => src.TheNestedClass.ANestedProperty)
);
// This is in my controller:
Flattened myFlattened = Mapper.Map<Root, Flattened>(myRoot);
我已经查看了许多示例,到目前为止,这似乎是扁平化嵌套层次结构的方法。但是,如果子对象具有多个属性,则此方法不会节省太多编码。
我找到了这个例子:
但它需要实例Map() 函数所需的映射对象的数量,据我了解,它不适用于配置文件。
我是 AutoMapper 的新手,所以我想知道是否有更好的方法来做到这一点。
I have been flattening domain objects into DTOs as shown in the example below:
public class Root
{
public string AParentProperty { get; set; }
public Nested TheNestedClass { get; set; }
}
public class Nested
{
public string ANestedProperty { get; set; }
}
public class Flattened
{
public string AParentProperty { get; set; }
public string ANestedProperty { get; set; }
}
// I put the equivalent of the following in a profile, configured at application start
// as suggested by others:
Mapper.CreateMap<Root, Flattened>()
.ForMember
(
dest => dest.ANestedProperty
, opt => opt.MapFrom(src => src.TheNestedClass.ANestedProperty)
);
// This is in my controller:
Flattened myFlattened = Mapper.Map<Root, Flattened>(myRoot);
I have looked at a number of examples, and so far this seems to be the way to flatten a nested hierarchy. If the child object has a number of properties, however, this approach doesn't save much coding.
I found this example:
but it requires instances of the mapped objects, required by the Map() function, which won't work with a profile as I understand it.
I am new to AutoMapper, so I would like to know if there is a better way to do this.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(8)
我更喜欢避免使用旧的静态方法并像这样做。
将我们的映射定义放入配置文件中。我们首先映射 Root,然后应用 Nested 的映射。请注意上下文的使用。
定义从 Root 到 Flattened 和 Nested 到 Flatterned 的映射的优点是,您可以保留对属性的映射,例如目标属性名称是否不同或者您想要应用转换等。XUnit
测试:
通过从AutoMapper.Extensions.Microsoft.DependencyInjection nuget 包添加到您的启动中,配置文件将自动获取,您只需将 IMapper 注入到应用映射的任何位置即可。
I much prefer avoiding the older Static methods and do it like this.
Place our mapping definitions into a Profile. We map the Root first, and then apply the mappings of the Nested afterwards. Note the use of the Context.
The advantage of defining both the mapping from Root to Flattened and Nested to Flatterned is that you retain full control over the mapping of the properties, such as if the destination property name is different or you want to apply a transformation etc.
An XUnit test:
By adding AutoMapper's serviceCollection.AddAutoMapper() from the AutoMapper.Extensions.Microsoft.DependencyInjection nuget package to your start up, the Profile will be picked up automatically, and you can simply inject IMapper into wherever you are applying the mapping.
在最新版本的 AutoMapper 中,您可以使用命名约定来避免多个 .ForMember 语句。
在您的示例中,如果您将 Flattened 类更新为:
您可以避免使用 ForMember 语句:
Automapper 将(按照惯例)将
Root.TheNestedClass.ANestedProperty
映射到Flattened.TheNestedClassANestedProperty< /代码> 在这种情况下。老实说,当您使用真实的类名时,它看起来不那么难看!
In the latest version of AutoMapper, there's a naming convention you can use to avoid multiple .ForMember statements.
In your example, if you update your Flattened class to be:
You can avoid the use of the ForMember statement:
Automapper will (by convention) map
Root.TheNestedClass.ANestedProperty
toFlattened.TheNestedClassANestedProperty
in this case. It looks less ugly when you're using real class names, honest!还有 2 个可能的解决方案:
另一种方法如下,但它不会通过 Mapper.AssertConfigurationIsValid()。
2 more possible solutions:
An alternative approach would be the below, but it would not pass the
Mapper.AssertConfigurationIsValid()
.不确定这是否会为以前的解决方案增加价值,但您可以将其作为两步映射来完成。如果父级和子级之间存在命名冲突(最后获胜),请小心按正确的顺序映射。
Not sure if this adds value to the previous solutions, but you could do it as a two-step mapping. Be careful to map in correct order if there are naming conflicts between the parent and child (last wins).
要改进另一个答案,请为两个映射指定
MemberList.Source
并将嵌套属性设置为忽略。然后验证通过就OK了。To improve upon another answer, specify
MemberList.Source
for both mappings and set the nested property to be ignored. Validation then passes OK.我编写了扩展方法来解决类似的问题:
因此,在您的情况下,可以像这样使用:
IgnoreAllNonExisting()
来自虽然它不是通用的解决方案,但对于简单的情况来说应该足够了。
因此,
I wrote extension method to solve similar problem:
So in your case it can be used like this:
IgnoreAllNonExisting()
is from here.Though it's not universal solution it should be enough for simple cases.
So,
我使用 AutoMappers 新命名约定规则创建了一个简单的示例,以从扁平对象映射到嵌套对象,希望这有助于
https://dotnetfiddle。网/i55UFK
I created a simple example using AutoMappers new naming convention rules to map from flattened to nested objects, hope this helps
https://dotnetfiddle.net/i55UFK
对于那些在这里绊倒寻找映射嵌套对象属性的方法,同时还利用 < code>属性映射,我希望您能够从以下内容中获得一些有价值的东西:
用法如下:
利用
params string[]
允许真正的任何深度的映射,继续添加即可参数越深,你需要走得越深。For anyone who stumbles here looking for a way to map Nested object properties while also leveraging
Attribute Mapping
, I am hoping you are able to pull something valuable from the following:Usage is as follows:
Leveraging the
params string[]
allows for really any depth of mapping, just continue to add the params the deeper you need to go.