gpt4 book ai didi

c# - 使用反射双向自动映射所有域实体以查看 MVC3 中的模型

转载 作者:行者123 更新时间:2023-11-30 16:27:21 24 4
gpt4 key购买 nike

由于我一直在使用和学习 ASP.Net MVC 3,所以我一直在使用 AutoMapper 在我的域的实体和我的 View 模型之间进行映射。

我厌倦了为我实现的每个 ViewModel 单独创建一个 map 。因此,我编写了一些代码来扫描我的程序集并使用一些反射来创建每个所需的映射。但是,因为我对使用 AutoMappers 的最佳实践不是很熟悉,所以我想我可以向大家展示我所做的一切,并询问我的方法是否可能会反噬我。

基本上我有一个名为 AutoMappingConfigurator 的类(在 Global.asax.cs 中使用),如下所示:

public static class AutoMappingConfigurator
{
public static void Configure(Assembly assembly)
{
var autoMappingTypePairingList = new List<AutoMappingTypePairing>();

foreach (Type t in assembly.GetTypes())
{
var autoMapAttribute = t
.GetCustomAttributes(typeof(AutoMapAttribute), true)
.OfType<AutoMapAttribute>()
.FirstOrDefault();

if (autoMapAttribute != null)
{
autoMappingTypePairingList
.Add(new AutoMappingTypePairing(autoMapAttribute.SourceType, t));
}
}

autoMappingTypePairingList
.ForEach(mappingPair => mappingPair.CreateBidirectionalMap());
}
}

本质上,它的作用是扫描程序集以查找所有已标记有 AutoMapAttribute 的类型,并为找到的每个类型创建一个双向映射。

AutoMapAttribute 是我创建的一个简单属性(基于我在网上找到的示例),我附加到我的 ViewModel 以指示它映射到哪个域实体。

例如。

[AutoMap(typeof(Project))]
public class ProjectDetailsViewModel
{
public int ProjectId { get; set; }
public string Name { get; set; }
public string Description { get; set; }
}

关于双向映射,到目前为止,在我使用 MVC3 的过程中,我发现我似乎经常需要为 HttpGet 从实体映射到 ViewModel,为 HttpPost 从 ViewModel 映射到实体。

双向映射作为扩展方法实现如下:

public static void CreateBidirectionalMap(this AutoMappingTypePairing mappingPair)
{
Mapper.CreateMap(mappingPair.SourceType, mappingPair.DestinationType)
.IgnoreProperties(mappingPair.DestinationType);

Mapper.CreateMap(mappingPair.DestinationType, mappingPair.SourceType)
.IgnoreProperties(mappingPair.SourceType);
}

关于 IgnoreProperties 扩展方法,我发现每当我有一个 View 模型有一个我想忽略的属性时(比如当我的 View 模型有一个不属于底层域实体的下拉列表时)我似乎必须通过 ForMember AutoMapper 方法手动创建忽略。因此,我创建了另一个属性来指示要忽略哪些属性,这样我在 AutoMappingConfigurator 中的反射代码可以自动为我执行此操作。

IgnoreProperties 扩展方法作为扩展方法实现如下:

public static IMappingExpression IgnoreProperties(this IMappingExpression expression
, Type mappingType)
{
var propertiesWithAutoMapIgnoreAttribute =
mappingType.GetProperties()
.Where(p => p.GetCustomAttributes(typeof(AutoMapIgnoreAttribute), true)
.OfType<AutoMapIgnoreAttribute>()
.Count() > 0);
foreach (var property in propertiesWithAutoMapIgnoreAttribute)
{
expression.ForMember(property.Name, opt => opt.Ignore());
}
return expression;
}

所有这些让我可以按如下方式编写我的 ViewModel 并自动映射它:

[AutoMap(typeof(EntityClass))]
private class ViewModelClass
{
public int EntityClassId { get; set; }

[AutoMapIgnore]
public IEnumerable<SelectListItem> DropDownItems { get; set; }
}

private class EntityClass
{
public int EntityClassId { get; set; }
}

虽然到目前为止这对我有用,但由于我对 AutoMapper 的经验不足,我担心它可能会回来咬我。

所以我的问题是:

  • 这是设置 AutoMapper 以配置我的映射的好方法吗在我的域实体和 ViewModel 之间?
  • 关于 AutoMapper 有什么我可能遗漏的东西会导致这是一个糟糕的方法吗?
  • 正在连接属性 Ignore by reflection 和 attributes a good想法?
  • 在我的实体和 ViewModel 之间创建双向映射是个好主意吗?

最佳答案

我更喜欢单向 View 模型。换句话说,我在向用户呈现数据时使用一个 View 模型,在处理创建时使用另一个 View 模型(另一个用于更新等)。

是的,您将通过这种方式获得更多对象。优点是您可以避免不需要的 View 模型属性(因此需要忽略它们)。我认为 View 模型应始终尽可能简单(简单的获取/设置属性,如果您有需要初始化的列表,则可能是构造函数)。如果您担心对象“公共(public)属性”的名称和数据类型,您可以(尽管我认为您不应该)在接口(interface)或基类中定义它们。

如果您想在两个 View 模型中使用某个域模型属性,则域模型中的 AutoMapIgnore 属性会出现问题。我认为这也适用于您的解决方案。

最后,我没有看到使用属性而不是像这样的代码行有什么好处

Mapper.CreateMap<SourceType, DestinationType>();

能再简单点吗?当您从 View 模型映射到模型时,拥有一个忽略“未映射属性”的扩展方法可能是个好主意,允许您编写

Mapper.CreateMap<SourceType, DestinationType>().IgnoreUnmappedProperties();

IMO 这比使用 AutoMapIgnore 属性更容易。

关于c# - 使用反射双向自动映射所有域实体以查看 MVC3 中的模型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8005455/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com