AutoMapper之ABP项目中的使用

最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客

AutoMapper只要用来数据转换,在园里已经有很多这方面文章了,本文主要介绍其在实际项目常用总结,以及在ABP项目中的应用介绍。AutoMapper应用非常简单,大家稍微看下文档就可以上手,但是性能不好啊,所以一般用在后台项目,对外的项目千万不要用。就那NOP来说吧,它也是把AutoMapper放在后台项目使用,商城前台的项目是不敢用的。

有关性能的问题本文没有涉及到,想了解的请参考EmitMapper,AutoMapper,NLiteMapper和手工映射性能大比拼 和 NLiteMapper与EmitMapper性能简单比较

下面主要讲下项目的入门和项目中的使用。

AutoMapper使用只要两步,配置和Mapper,一般的在项目中我们会在Global中进行配置

配置映射关系

1
2
3
4
5
6
7
8
9
10
11
12
public class Source
{
   public int SomeValue { getset; }
}
 
public class Destination
{
   public int SomeValue { getset; }
}
 
//这个就是配置映射关系
Mapper.CreateMap<Source, Destination>();

然后就是Mapper

1
2
3
4
5
6
7
Source source = new Source()
{
    SomeValue = 1
};
 
var destination = Mapper.Map<Source, Destination>(source);
Console.WriteLine(destination.SomeValue);//1

是不是很简单,这是最简单的使用了,当然AutoMapper是个“机关枪”,这个只是它的最简单使用。下面在介绍几点常用的功能。还是上面那个例子,只是字段变了

1
2
3
4
5
6
7
8
9
10
11
public class Source
{
    public int SomeValue { getset; }
}
 
public class Destination
{
    public int SomeValuefff { getset; }
}
 
Mapper.CreateMap<AddressDto, Address>();

这样子字段都不一样明细是不能映射的嘛,所有呢我们可以用Mapper.AssertConfigurationIsValid()来验证,就会AutoMapperConfigurationException异常,

选择忽略相关字段

1
2
Mapper.CreateMap<Source, Destination>()
        .ForMember(dest => dest.SomeValuefff, opt => opt.Ignore());

类型转换,自定义类型转换

1
2
3
4
5
6
7
8
9
10
11
12
13
public class Source
{
    public string Value1 { getset; }
    public string Value2 { getset; }
    public string Value3 { getset; }
}
 
public class Destination
{
    public int Value1 { getset; }
    public DateTime Value2 { getset; }
    public Type Value3 { getset; }
}

Source要转Destination,但是第二和第三的字段类型都不一致,所以我们可以自定义类型转换,下面看下转换函数ConvertUsing一般最常用第二种,接受一个ITypeConverter

1
2
3
void ConvertUsing(Func<TSource, TDestination> mappingFunction);
void ConvertUsing(ITypeConverter<TSource, TDestination> converter);
void ConvertUsing<TTypeConverter>() where TTypeConverter : ITypeConverter<TSource, TDestination>;

下面看下ITypeConverter接口

1
2
3
4
public interface ITypeConverter<TSource, TDestination>
{
    TDestination Convert(ResolutionContext context);
}

我们可以继承这个接口队Convert进行重写

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
public class DateTimeTypeConverter : ITypeConverter<string, DateTime>
{
    public DateTime Convert(ResolutionContext context)
    {
        return System.Convert.ToDateTime(context.SourceValue);
    }
}
 
public class TypeTypeConverter : ITypeConverter<string, Type>
{
    public Type Convert(ResolutionContext context)
    {
          return context.SourceType;
    }
}

这样我们就可以映射了,下面看下完整代码

好了,上面把 AutoMapper在项目中常用的方法都介绍完了,再介绍ABP之前我们先看下NOP是怎么使用的吧,由于代码较长省略部分

好了,终于可以到ABP的了,ABP对AutoMapper的使用总结出来两点,1、在模块中初始化配置,2、遍历bin目录下所有的Types判断哪些类是否被定义为需要转换的Attribute

在模块中初始化配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
public class AbpAutoMapperModule : AbpModule
{
    private readonly ITypeFinder _typeFinder;
 
    private static bool _createdMappingsBefore;
    private static readonly object _syncObj = new object();
     
    public AbpAutoMapperModule(ITypeFinder typeFinder)
    {
        _typeFinder = typeFinder;
    }
 
    private void FindAndAutoMapTypes()
    {
        var types = _typeFinder.Find(type =>
            type.IsDefined(typeof(AutoMapAttribute)) ||
            type.IsDefined(typeof(AutoMapFromAttribute)) ||
            type.IsDefined(typeof(AutoMapToAttribute))
            );
 
        foreach (var type in types)
        {
            AutoMapperHelper.CreateMap(type);
        }
    }
}

AbpAutoMapperModule 模块会在Global的时候被初始化,然后在PreInitialize的时候回调用到FindAndAutoMapTypes,有关模块是怎么初始化的我想再写一篇介绍。下面我们看下_typeFinder吧

上面_typeFinder.Find调用的是TypeFinder的Find方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
public Type[] Find(Func<Type, bool> predicate)
{
    return GetAllTypes().Where(predicate).ToArray();
}
 
public Type[] FindAll()
{
    return GetAllTypes().ToArray();
}
 
private List<Type> GetAllTypes()
{
    var allTypes = new List<Type>();
 
    foreach (var assembly in AssemblyFinder.GetAllAssemblies().Distinct())
    {
        try
        {
            Type[] typesInThisAssembly;
 
            try
            {
                typesInThisAssembly = assembly.GetTypes();
            }
            catch (ReflectionTypeLoadException ex)
            {
                typesInThisAssembly = ex.Types;
            }
 
            if (typesInThisAssembly.IsNullOrEmpty())
            {
                continue;
            }
 
            allTypes.AddRange(typesInThisAssembly.Where(type => type != null));
        }
        catch (Exception ex)
        {
            Logger.Warn(ex.ToString(), ex);
        }
    }
 
    return allTypes;
}

好吧,上面代码有点多,但是很简单,就是获取所有的Types,我们看下关键代码AssemblyFinder.GetAllAssemblies()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public class WebAssemblyFinder : IAssemblyFinder
{
    /// <summary>
    /// This return all assemblies in bin folder of the web application.
    /// </summary>
    /// <returns>List of assemblies</returns>
    public List<Assembly> GetAllAssemblies()
    {
        var assembliesInBinFolder = new List<Assembly>();
 
        var allReferencedAssemblies = BuildManager.GetReferencedAssemblies().Cast<Assembly>().ToList();
        var dllFiles = Directory.GetFiles(HttpRuntime.AppDomainAppPath + "bin\\""*.dll", SearchOption.TopDirectoryOnly).ToList();
 
        foreach (string dllFile in dllFiles)
        {
            var locatedAssembly = allReferencedAssemblies.FirstOrDefault(asm => AssemblyName.ReferenceMatchesDefinition(asm.GetName(), AssemblyName.GetAssemblyName(dllFile)));
            if (locatedAssembly != null)
            {
                assembliesInBinFolder.Add(locatedAssembly);
            }
        }
 
        return assembliesInBinFolder;
    }
}

看看吧,这代码是或bin目录下面的dll,好丧心病狂啊,回到刚刚AbpAutoMapperModule 的获取FindAndAutoMapTypes方法。在获取所有的Types之后我们就要判断这个类是否是被标识了

AutoMapAttribute、AutoMapFromAttribute和AutoMapToAttribute

1
2
3
4
5
6
7
8
9
10
11
12
13
private void FindAndAutoMapTypes()
{
    var types = _typeFinder.Find(type =>
        type.IsDefined(typeof(AutoMapAttribute)) ||
        type.IsDefined(typeof(AutoMapFromAttribute)) ||
        type.IsDefined(typeof(AutoMapToAttribute))
        );
 
    foreach (var type in types)
    {
        AutoMapperHelper.CreateMap(type);
    }
}

获取之后再我下的Demo中就只有一个UserDto类被标识了 

1
2
3
4
5
6
7
8
9
10
11
12
13
14
namespace AbpDemo.Application.Users.Dto
{
    [AutoMapFrom(typeof(User))]
    public class UserDto : EntityDto<long>
    {
        public string UserName { getset; }
 
        public string Name { getset; }
         
        public string Surname { getset; }
         
        public string EmailAddress { getset; }
    }
}

接下来就是遍历所有的types进行配置了AutoMapperHelper.CreateMap(type);配置也很简单 看下代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
public static void CreateMap<TAttribute>(Type type)
    where TAttribute : AutoMapAttribute
{
    if (!type.IsDefined(typeof (TAttribute)))
    {
        return;
    }
 
    foreach (var autoMapToAttribute in type.GetCustomAttributes<TAttribute>())
    {
        if (autoMapToAttribute.TargetTypes.IsNullOrEmpty())
        {
            continue;
        }
 
        foreach (var targetType in autoMapToAttribute.TargetTypes)
        {
            if (autoMapToAttribute.Direction.HasFlag(AutoMapDirection.To))
            {
                Mapper.CreateMap(type, targetType);
            }
 
            if (autoMapToAttribute.Direction.HasFlag(AutoMapDirection.From))
            {
                Mapper.CreateMap(targetType, type);                               
            }
        }
    }
}

好了,表达能力不是很好,各位就勉强看下吧。终于写完了。发现作者很喜欢用Attribute来过滤。这边AutoMapper是这样,UnitOfWork也是这样,其实这样也是挺方便的,有点AOP的切面的感觉,值得学习。 

参考文章:

http://www.cnblogs.com/netcasewqs/archive/2011/04/13/2014684.html

http://www.cnblogs.com/repository/archive/2011/04/08/2009713.html

https://github.com/AutoMapper/AutoMapper/wiki/Configuration-validation

http://www.cnblogs.com/youring2/p/automapper.html

http://www.cnblogs.com/1-2-3/p/AutoMapper-Best-Practice.html

ABP项目中的使用AutoMapper的更多相关文章

  1. AutoMapper之ABP项目中的使用介绍

    最近在研究ABP项目,昨天写了Castle Windsor常用介绍以及其在ABP项目的应用介绍 欢迎各位拍砖,有关ABP的介绍请看阳光铭睿 博客 AutoMapper只要用来数据转换,在园里已经有很多 ...

  2. 说说ABP项目中的AutoMapper,Castle Windsor(痛并快乐着)

    这篇博客要说的东西跟ABP,AutoMapper和Castle Windsor都有关系,而且也是我在项目中遇到的问题,最终解决了,现在的感受就是“痛并快乐着”. 首先,这篇博客不是讲什么新的知识点,而 ...

  3. ABP项目中使用Swagger生成动态WebAPI

    本文是根据角落的白板报的<使用ABP实现SwaggerUI,生成动态webapi>一文的学习总结,感谢原文作者角落的白板报. 1 安装Swashbuckle.core 1.1 选择WebA ...

  4. 在基于AngularJs架构的ABP项目中使用UEditor

    [前提须知] 读过此篇博客 了解angular-ueditor 了解ABP如何使用 会使用VS2017 [1.下载ABP模板] https://aspnetboilerplate.com/Templa ...

  5. Abp项目中的领域模型实体类访问仓储的方法

    首先声明,不推荐使用这种方法.实体访问仓储是不被推荐的! 1.简单粗暴的方法 Abp.Dependency.IocManager.Instance.Resolve>(); 2.绕个弯子的方法 首 ...

  6. abp项目中无法使用HttpContext.Current.Session[""]的问题

    web项目Global.asax.cs中加入如下代码 public override void Init() { this.PostAuthenticateRequest += (sender, e) ...

  7. AutoMapper在ABP框架中的使用说明

    为了说明AutoMapper如何使用,我专门开设了一个专题来讲,如果您还没有查看该专题,请点击这里.既然系统地学习了AutoMapper,那么接下来就是该用它实战的时候了.今天,我们就来揭开AutoM ...

  8. 在 ASP.NET Core 项目中使用 AutoMapper 进行实体映射

    一.前言 在实际项目开发过程中,我们使用到的各种 ORM 组件都可以很便捷的将我们获取到的数据绑定到对应的 List<T> 集合中,因为我们最终想要在页面上展示的数据与数据库实体类之间可能 ...

  9. Castle Windsor常用介绍以及其在ABP项目的应用介绍

    最近在研究ABP项目,有关ABP的介绍请看阳光铭睿 博客,ABP的DI和AOP框架用的是Castle Windsor下面就对Castle Windsor项目常用方法介绍和关于ABP的使用总结 1.下载 ...

随机推荐

  1. Automatically generate serial number in abap

    流水号的产生:   在ABAP开发中,很多地方都需要按照自己的规则生成流水号,把这些流水号保存进透明表,作为唯一标示. 一. 系统中设定流水号 使用T-Code SNRO来创建一个流水号标识对象. 输 ...

  2. C#的c/s做出开灯关灯计算?

    static void light(Boolean[] lights,int n) {     if (n <= 1 || lights.Length<5) return;     for ...

  3. C语言static 具体分析

    google在最后三页C语言static内容,可找到的资料非常少.无论是长篇大论不知所云的话,在关键位置或跳过,习的人来说參考性不是非常大.所以.我这篇博文博採众家之长,把互联网上的资料整合归类,并亲 ...

  4. Windows 8 应用开发 - 应用栏

    原文:Windows 8 应用开发 - 应用栏      通过应用栏(AppBar)可以在需要时向用户显示各种应用命令.应用栏提供与用户当前页面或当前选定的内容相关的各种命令.默认情况下,应用栏处于隐 ...

  5. 重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView

    原文:重新想象 Windows 8 Store Apps (11) - 控件之 ListView 和 GridView [源码下载] 重新想象 Windows 8 Store Apps (11) - ...

  6. android Animation动画的xml使用

    在Android应用程序,使用动画效果,能带给用户更好的感觉,做动画能够通过XML或Android代码来实现. Animation动画效果的实现能够通过两种方式进行实现,一种是tweened anim ...

  7. MYSQL IFNULL使用功能

    稍后的MYSQL IFNULL使用此功能的特定叙事,供大家参考学习,假设你MYSQL IFNULL条款的使用功能类别遇到似问题.最好看. MYSQL IFNULL(expr1,expr2)       ...

  8. Nutch 二次开发parse纸

    大约nutch基础知识可以参考lemo柱 nutch支持二次开发,为了满足搜索的准确性的问题,内容提取出来作为索引的内容,相应的是parse_text的数据.我使用的事nutch1.4 版本号,在cy ...

  9. zoj 1738 - Lagrange&#39;s Four-Square Theorem

    称号:四方形定理.输出可以表示为一个数目不超过四个平方和表示的数. 分析:dp,完全背包.背包分割整数.可用一维分数计算,它也可以被写为一个二维团结. 状态:设f(i,j,k)为前i个数字,取j个数字 ...

  10. HDOJ 5188 zhx and contest 贪婪+01背包

    zhx and contest Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) ...