1 Core.Infrastructure.Mapper.IOrderedMapperProfile

namespace Core.Infrastructure.Mapper

{

    /// <summary>

    /// 【映射配置文件顺序--接口】

    /// <remarks>

    /// 摘要:

    ///    通过该接口中的属性成员,来限定继承于该接口具体实现类被实例化的顺序。

    /// </remarks>

    /// </summary>

    public interface IOrderedMapperProfile

    {

        /// <summary>

        /// 【顺序】

        /// <remarks>

        /// 摘要:

        ///     继承于当前接口的所有的具体实现类,被实例化时顺序;即在通过该接口批量实例化所有的具体实现类时,

        /// 将按照指定具体实现类该属性成员值进行实例化。

        /// </remarks>

        /// </summary>

        int Order { get; }

    }

}

2 Core.Infrastructure.Mapper.AutoMapperConfiguration

using AutoMapper;

namespace Core.Infrastructure.Mapper

{

    /// <summary>

    /// 【自动映射配置--类】

    /// <remarks>

    /// 摘要:

    ///    通过该类中拷贝构造方法,对当前程序中的两个指定实例之间赋值操作映射规则,及其赋值操作进行实例化,并对它们进行集中管理。

    /// </remarks>

    /// </summary>

    public static class AutoMapperConfiguration

    {

        #region 属性

        /// <summary>

        /// 【映射器】

        /// <remarks>

        /// 摘要:

        ///     获取/设置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。

        /// </remarks>

        /// </summary>

        public static IMapper Mapper { get; private set; }

        /// <summary>

        /// 【映射配置】

        /// <remarks>

        /// 摘要:

        ///     获取/设置两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。

        /// </remarks>

        /// </summary>

        public static MapperConfiguration MapperConfiguration { get; private set; }

        #endregion

        #region 方法

        /// <param name="config">两个不同类型实例赋值操作之间的映射规则实例。</param>

        /// <summary>

        /// 【实例化】

        /// <remarks>

        /// 摘要:

        ///     通过该方法实例化当前类中的两个静态属性成员:

        ///     1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。

        ///     2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。

        /// </remarks>

        /// </summary>

        public static void Init(MapperConfiguration config)

        {

            MapperConfiguration = config;

            Mapper = config.CreateMapper();

        }

        #endregion

    }

}

3 Core.Infrastructure.Engine.AddAutoMapper

 /// <summary>

        /// 【添加自动映射】

        /// <remarks>

        /// 摘要:

        ///    实例化映射规则实例和映射器接口实例:

        ///    1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。

        ///    2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。

        /// </remarks>

        /// </summary>

        protected virtual void AddAutoMapper()

        {

            //从单例实例的字典成员实例中获取获取Web应用程序域类型查找器实例。

            var typeFinder = Singleton<ITypeFinder>.Instance;

            //获取继承于“IOrderedMapperProfile”的所有具体实现类的类型实例。

            var mapperConfigurations = typeFinder.FindClassesOfType<IOrderedMapperProfile>();

            //通过反射方式把继承于“IOrderedMapperProfile”的所有具体实现类进行实例化操作。

            var instances = mapperConfigurations

                .Select(mapperConfiguration => (IOrderedMapperProfile)Activator.CreateInstance(mapperConfiguration))

                .OrderBy(mapperConfiguration => mapperConfiguration.Order);

            //依次把两个指定实例之间赋值映射规则进行实例化。

            var config = new MapperConfiguration(cfg =>

            {

                foreach (var instance in instances)

                {

                    cfg.AddProfile(instance.GetType());

                }

            });

              // 实例化两个实例,

            //    1、两个不同类型实例赋值操作之间的映射规则实例,该实例为映射器接口的实例化提供映射规则实例支持。

            //    2、实例化置映射器接口实例,通过该实例的成员方法实现两个指定实例之间赋值操作。

            AutoMapperConfiguration.Init(config);

        }

4 Core.Infrastructure.Engine.ConfigureServices

  /// <param name="services">.NetCore框架内置依赖注入容器接口实例。</param>

        /// <param name="configuration">.NetCore框架内置配置接口实例(存储着当前程序中所有*.json文件中的数据)</param>

        /// <summary>

        /// 【配置服务】

        /// <remarks>

        /// 摘要:

        ///      把具体现类和中间件注入到内置依赖注入容器后,把“Engine”实例存储到单例实例的字典成员实例中,同时把.NetCore框架内置依赖注入容器接口实例所存储的当前程序中的具体现类和中间件的实例通过“Engine”(引擎)单例实例存储到单例类的字典属性成员实例中。

        /// 说明:

        ///     1“Engine”实例用于对.NetCore框架内置依赖注入容器接口实例所存储的当前程序中的具体现类和中间件的实例进行集中管理。

        ///     2“Engine”实例是单例的,即在程序运行过程中“Engine”实例是唯一的,该实例,在运行过程序中只能被替换(同内存的1个引用地址),而不能再次被实例化1(两个不内存的引用地址)

        /// </remarks>

        /// </summary>

        public virtual void ConfigureServices(IServiceCollection services, IConfiguration configuration)

        {

            //“Engine”实例存储到单例实例的字典成员实例中。

            services.AddSingleton<IEngine>(this);

            //从单例实例的字典成员实例中获取获取Web应用程序域类型查找器实例。

            var typeFinder = Singleton<ITypeFinder>.Instance;

            //获取继承于“IStartup”的所有具体实现类的类型实例。

            var startupConfigurations = typeFinder.FindClassesOfType<IStartup>();

            //通过反射方式把继承于“IStartup”的所有具体实现类进行实例化操作。

            var instances = startupConfigurations

                .Select(startup => (IStartup)Activator.CreateInstance(startup))

                .OrderBy(startup => startup!.Order);

            //把继承于“IStartup”的所有具体实现类的实例,依赖注入到.Net(Core)内置依赖注入容器实例中。

            foreach (var instance in instances)

                instance!.ConfigureServices(services, configuration);

            AddAutoMapper();

            services.AddSingleton(services);

        }

5 Framework.Models.BaseEntityModel

namespace Framework.Models

{

    /// <summary>

    /// 【基实体模型--纪录】

    /// <remarks>

    /// 摘要:

    ///     1、所有的模型纪录通过继承该模型纪录,以获取相应的的长整型编号值。

    /// </remarks>

    /// </summary>

    public record BaseEntityModel

    {

        /// <summary>

        /// 【编号】

        /// <remarks>

        /// 摘要:

        ///     获取/设置所有模型纪录实例的长整型编号值。

        /// </remarks>

        /// </summary>

        public virtual int Id { get; set; }

    }

}

6 Web.Areas.Admin.Infrastructure.Mapper.AdminMapperConfiguration

using AutoMapper;

using AutoMapper.Internal;

using Core.Domain.Customers;

using Core.Infrastructure.Mapper;

using Web.Areas.Admin.Models.Customers;

namespace Web.Areas.Admin.Infrastructure.Mapper

{

    /// <summary>

    /// 【自动映射配置--类】

    /// <remarks>

    /// 摘要:

    ///    通过该类中拷贝构造方法,对当前程序中的两个指定实例之间赋值操作映射规则,及其赋值操作进行实例化,并对它们进行集中管理。

    /// </remarks>

    /// </summary>

    public partial class AdminMapperConfiguration : Profile, IOrderedMapperProfile

    {

        #region 拷贝构造方法

        /// <summary>

        /// 【拷贝构造方法】

        /// <remarks>

        /// 摘要:

        ///     通过该拷贝构造方法,对当前程序中的两个指定实例之间赋值操作映射规则,及其赋值操作进行实例化,并对它们进行集中管理。

        /// </remarks>

        /// </summary>

        public AdminMapperConfiguration()

        {

            CreateCustomersMaps();

            //“ForAllMaps”方法为两个指定实例执行赋值操作时为特定赋值操作定义相应的映射规则(例如:“Ignore”,即在两个指定实例执行赋值操作时,忽略指定的属性成员实例)

            this.Internal().ForAllMaps((mapConfiguration, map) =>

            {

            });

        }

        #endregion

        #region 属性

        /// <summary>

        /// 【顺序】

        /// <remarks>

        /// 摘要:

        ///     当前具体实现类被实例化时的顺序。

        /// </remarks>

        /// </summary>

        public int Order => 0;

        #endregion

        #region 方法--私通/保护

        /// <summary>

        /// 【新建用户配置映射】

        /// <remarks>

        /// 摘要:

        ///     该方法用于与用户相关的两个实例之间的赋值操作定义进行集中管理。

        /// </remarks>

        /// </summary>

        protected virtual void CreateCustomersMaps()

        {

            CreateMap<Role, RoleModel>();

            CreateMap<RoleModel, Role>();

        }

        #endregion

    }

}

7 Web.Areas.Admin.Infrastructure.Mapper.Extensions.MappingExtensions

using Core.Domain;

using Core.Infrastructure.Mapper;

using Framework.Models;

namespace Web.Areas.Admin.Infrastructure.Mapper.Extensions

{

    /// <summary>

    /// 【映射扩展--类】

    /// <remarks>

    /// 摘要:

    ///    该类中方法成员通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。

    /// </remarks>

    /// </summary>

    public static class MappingExtensions

    {

        #region 方法--私通/保护

        /// <typeparam name="TDestination">泛型类型实例(1个指定类型实例,该类型实例为被赋值操作,提供实例支撑)</typeparam>

        /// <param name="source">泛型实例这里特指:1个指定类的1个指定实例,该实例为赋值操作提供数据源。</param>

        /// <summary>

        /// 【映射】

        /// <remarks>

        /// 摘要:

        ///     该方法通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的另1个指定类型的1个指定实例。

        /// </returns>

        /// </summary>

        private static TDestination Map<TDestination>(this object source)

        {

            return AutoMapperConfiguration.Mapper.Map<TDestination>(source);

        }

        /// <typeparam name="TSource">泛型类型实例(1个指定类型实例,该类型实例为赋值操作,提供数据源支撑)</typeparam>

        /// <typeparam name="TDestination">泛型类型实例(1个指定类型实例,该类型实例为被赋值操作,提供实例支撑)</typeparam>

        /// <param name="source">1个指定类的1个指定实例,该实例为赋值操作提供数据源。</param>

        /// <param name="destination">1个指定类的1个指定实例,该实例为赋值操作提供转换目标。</param>

        /// <summary>

        /// 【映射到】

        /// <remarks>

        /// 摘要:

        ///     该方法通过对“AutoMapperConfiguration”的进一步封装,两个不同类型指定实例之间赋值操作。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的另1个指定类型的1个指定实例。

        /// </returns>

        /// </summary>

        private static TDestination MapTo<TSource, TDestination>(this TSource source, TDestination destination)

        {

            return AutoMapperConfiguration.Mapper.Map(source, destination);

        }

        #endregion

        //实际上以下方法为上面私有方法的过滤实现,如果相简化实现只要的把上面的私有方法更改为公有方法也只很好的实现两个不同类型指定实例之间赋值操作。

        #region 模型纪录实例与实体实例的赋值实现

        /// <typeparam name="TModel">泛型模型纪录的类型实例(模型纪录的类型实例,为被赋值操作,提供实例支撑)</typeparam>

        /// <param name="source">泛型实例这里特指:1个指定实体的1个指定实例,为赋值操作,提供数据源支撑。</param>

        /// <summary>

        /// 【映射到模型】

        /// <remarks>

        /// 摘要:

        ///     1个指定实体的1个指定实例赋值给1个指定模型纪录的1个指定实例

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的1个指定模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        public static TModel ToModel<TModel>(this BaseEntity entity) where TModel : BaseEntityModel

        {

            if (entity == null)

                throw new ArgumentNullException(nameof(entity));

            return entity.Map<TModel>();

        }

        /// <typeparam name="TEntity">泛型实体的类型实例(1个指定实体的类型实例,为赋值操作,提供数据源支撑)</typeparam>

        /// <typeparam name="TModel">泛型模型纪录的类型实例(模型纪录的类型实例,为被赋值操作,提供实例支撑)</typeparam>

        /// <param name="entity">泛型实例这里特指:1个指定实体的1个指定实例,为赋值操作,提供数据源支撑</param>

        /// <param name="model">1个指定模型纪录的1个指定实例,为被赋值操作,提供实例支撑。</param>

        /// <summary>

        /// 【映射到模型】

        /// <remarks>

        /// 摘要:

        ///     1个指定实体的1个指定实例赋值给1个指定模型纪录的1个指定实例

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的1个指定模型纪录的1个指定实例。

        /// </returns>

        /// </summary>

        public static TModel ToModel<TEntity, TModel>(this TEntity entity, TModel model)

            where TEntity : BaseEntity where TModel : BaseEntityModel

        {

            if (entity == null)

                throw new ArgumentNullException(nameof(entity));

            if (model == null)

                throw new ArgumentNullException(nameof(model));

            return entity.MapTo(model);

        }

        /// <typeparam name="TEntity">泛型实体的类型实例(1个指定实体的类型实例,为被赋值操作,提供实例支撑)</typeparam>

        /// <param name="model">1个指定模型纪录的1个指定实例,为赋值操作,提供数据源支撑。</param>

        /// <summary>

        /// 【映射到实体】

        /// <remarks>

        /// 摘要:

        ///     1个指定实体的1个指定实例赋值给1个指定模型纪录的1个指定实例

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的指定1个指定实体的1个指定实例。

        /// </returns>

        /// </summary>

        public static TEntity ToEntity<TEntity>(this BaseEntityModel model) where TEntity : BaseEntity

        {

            if (model == null)

                throw new ArgumentNullException(nameof(model));

            return model.Map<TEntity>();

        }

        /// <typeparam name="TEntity">泛型实体的类型实例(1个指定实体的类型实例,为被赋值操作,提供实例支撑)</typeparam>

        /// <typeparam name="TModel">泛型模型纪录的类型实例(模型纪录的类型实例,为赋值操作,提供数据源支撑)</typeparam>

        /// <param name="entity">泛型实例这里特指:1个指定实体的1个指定实例,为被赋值操作,提供实例支撑。</param>

        /// <param name="model">1个指定模型纪录的1个指定实例,为赋值操作,提供数据源支撑。</param>

        /// <summary>

        /// 【映射到实体】

        /// <remarks>

        /// 摘要:

        ///     1个指定实体的1个指定实例赋值给1个指定模型纪录的1个指定实例

        /// </remarks>

        /// <returns>

        /// 返回:

        ///    被赋值后的指定1个指定实体的1个指定实例。

        /// </returns>

        /// </summary>

        public static TEntity ToEntity<TEntity, TModel>(this TModel model, TEntity entity)

            where TEntity : BaseEntity where TModel : BaseEntityModel

        {

            if (model == null)

                throw new ArgumentNullException(nameof(model));

            if (entity == null)

                throw new ArgumentNullException(nameof(entity));

            return model.MapTo(entity);

        }

        #endregion

    }

}

8 重构Web.Areas.Admin.Controllers.RoleController

using Core.Domain.Customers;

using Microsoft.AspNetCore.Mvc;

using Services.Customers;

using Web.Areas.Admin.Infrastructure.Mapper.Extensions;

using Web.Areas.Admin.Models.Customers;

namespace Web.Areas.Admin.Controllers

{

    [Area("Admin")]

    public class RoleController : Controller

    {

        #region 拷贝构造方法与变量

        private readonly ICustomerService _customerService;

        /// <summary>

        /// 【拷贝构建方法】

        /// <remarks>

        /// 摘要:

        ///     依赖注入容器通过拷贝构造方法,实例化该类中的变量成员。

        /// </remarks>

        /// </summary>

        public RoleController(ICustomerService customerService)

        {

            _customerService = customerService;

        }

        #endregion

        #region Razor页面中输入的自动验证

        /// <param name="name">被验证的角色名。</param>

        /// <param name="id">被验证角色名所对应的长整型编号值,默认值:0,用户角色实例的新建。</param>

        /// <summary>

        /// 【唯一角色名】

        /// <remarks>

        /// 摘要:

        ///     通过相应的参数实例,远程验证表单中所输入的用户名是否已经被注册。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     JSON编码格式的验证结果状态信息。

        /// </returns>

        /// </summary>

        public async Task<IActionResult> UniqueName(string name, long id = 0)

        {

            Role _role = (await _customerService.GetAllRolesAsync(true)).Where(role => role.Name.ToLower().Equals(name.Trim().ToLower())).FirstOrDefault();

            if (_role != null && _role.Id != id)

                return Json($"该角色名已经被使用。");

            return Json(true);

        }

        #endregion

        #region CURD

        /// <summary>

        /// 【角色列表】

        /// <remarks>

        /// 摘要:

        ///     获取角色实体的所有实例,为角色列表Razor页面的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        ///    1个列表实例,该实例存储着角色实体的所有实例。

        /// </returns>

        /// </summary>

        public async Task<IActionResult> Index()

        {

            IList<Role> _roleList = await _customerService.GetAllRolesAsync(true);

            return View(_roleList);

        }

        /// <summary>

        /// 【添加角色】

        /// <remarks>

        /// 摘要:

        ///     获取角色实体的1个空实例,为添加角色Razor页面的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     角色实体的1个空实例。

        /// </returns>

        /// </summary>

        public IActionResult Create()

        {

            return View();

        }

        /// <param name="model">角色模型记录的1个指定实例。</param>

        /// <summary>

        /// 【添加角色】

        /// <remarks>

        /// 摘要:

        ///     通过添加角色Razor页面中的数据,把角色实体的1个指定实例持久化到角色表中。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     角色模型记录的1个指定实例。

        /// </returns>

        /// </summary>

        [HttpPost]

        public async Task<IActionResult> Create(RoleModel model)

        {

            var role = model.ToEntity(new Role());

            role.Active = true;

            await _customerService.InsertRoleAsync(role);

            ViewBag.RefreshPage = true;

            return View(model);

        }

        /// <param name="id">1个指定的长整型编号值。</param>

        /// <summary>

        /// 【修改角色】

        /// <remarks>

        /// 摘要:

        ///     获取角色实体的1个指定实例,为修改角色Razor页面的渲染显示提供数据支撑。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     角色模型记录的1个指定实例。

        /// </returns>

        /// </summary>

        public async Task<IActionResult> Edit(long id)

        {

            var role = await _customerService.GetRoleByIdAsync(id);

            var model = role.ToModel(new RoleModel());

            return View(model);

        }

        /// <param name="model">角色模型记录的1个指定实例。</param>

        /// <summary>

        /// 【修改角色】

        /// <remarks>

        /// 摘要:

        ///     通过更新角色Razor页面中的数据,把角色实体的1个指定实例持久化更新到角色表中。

        /// </remarks>

        /// <returns>

        /// 返回:

        ///     角色模型记录的1个指定实例。

        /// </returns>

        /// </summary>

        [HttpPost]

        public async Task<IActionResult> Edit(RoleModel model)

        {

            var role = model.ToEntity(new Role());

            await _customerService.UpdateRoleAsync(role);

            ViewBag.RefreshPage = true;

            return View(model);

        }

        #endregion

    }

}

对以上功能更为具体实现和注释见230524_015ShopRazor(通过AutoMapper实现自动赋值映射操作)。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐