网站首页 网站源码
website
站点相关全部源代码,隐藏了一些关于服务器的信息
using System;
using System.Linq;
using System.Reflection;
using AutoMapper;
using MongoDB.Bson;

namespace Dpz.Core.Infrastructure.MapperConfig;

public class GlobalConfigMapper
{
    private static readonly Lazy<GlobalConfigMapper> LazyMapper = new(() => new GlobalConfigMapper());

    private GlobalConfigMapper()
    {
        Mapper = ConfigGlobalMapper();
    }

    public IMapper Mapper { get; }

    public static GlobalConfigMapper GetInstance()
    {
        return LazyMapper.Value;
    }

    public static GlobalConfigMapper Instance => LazyMapper.Value;

    private static IMapper ConfigGlobalMapper()
    {
        var types = Assembly.Load("Dpz.Core.Public.ViewModel").GetExportedTypes();
        var config = new MapperConfigurationExpression();
        // 1. 传统的 IMapFrom<T> 接口映射
        ConfigureIMapFromMappings(types, config);

        // 2. 静态接口映射
        ConfigureStaticInterfaceMappings(types, config);

        // 3. 基于特性的映射
        ConfigureAttributeBasedMappings(types, config);
        
        // 4. 内置映射规则
        ConfigureBuiltInMappings(config);

        var cfg = new MapperConfiguration(config);
        IMapper mapper = new Mapper(cfg);
        return mapper;
    }

    /// <summary>
    /// 配置 IMapFrom 接口映射
    /// </summary>
    private static void ConfigureIMapFromMappings(
        Type[] types,
        MapperConfigurationExpression config
    )
    {
        var maps =
            from x in types
            from y in x.GetInterfaces()
            let faceType = y.GetTypeInfo()
            where
                faceType.IsGenericType
                && y.GetGenericTypeDefinition() == typeof(IMapFrom<>)
                && !x.IsAbstract
                && !x.IsInterface
            select new { Source = y.GetGenericArguments()[0], Destination = x };

        foreach (var item in maps)
        {
            config.CreateMap(item.Source, item.Destination);
            config.CreateMap(item.Destination, item.Source);
        }
    }

    /// <summary>
    /// 配置静态接口映射(C# 11+)
    /// </summary>
    private static void ConfigureStaticInterfaceMappings(
        Type[] types,
        MapperConfigurationExpression config
    )
    {
        var staticMappingTypes = types.Where(x =>
            x.GetInterfaces().Any(i => i == typeof(IHaveCustomMapping))
            && x is { IsAbstract: false, IsInterface: false }
        );

        foreach (var type in staticMappingTypes)
        {
            // 调用静态方法
            var method = type.GetMethod(
                nameof(IHaveCustomMapping.CreateMappings),
                BindingFlags.Static | BindingFlags.Public,
                null,
                [typeof(MapperConfigurationExpression)],
                null
            );
            method?.Invoke(null, [config]);
        }
    }

    /// <summary>
    /// 配置基于特性的映射
    /// </summary>
    private static void ConfigureAttributeBasedMappings(
        Type[] types,
        MapperConfigurationExpression config
    )
    {
        foreach (var type in types)
        {
            var mappingAttributes = type.GetCustomAttributes<AutoMappingAttribute>();
            foreach (var attr in mappingAttributes)
            {
                attr.ConfigureMapping(config);
            }
        }
    }

    /// <summary>
    /// 配置内置映射规则
    /// </summary>
    private static void ConfigureBuiltInMappings(MapperConfigurationExpression config)
    {
        config
            .CreateMap<string, ObjectId>()
            .ConstructUsing(
                (x, _) =>
                    !string.IsNullOrEmpty(x) && ObjectId.TryParse(x, out var oid)
                        ? oid
                        : ObjectId.Empty
            );
    }
}
⚠⚠    以下内容为AI分析的结果,请根据实际情况进行判断。

上述代码定义了一个名为 GlobalConfigMapper 的类,主要用于配置和管理 AutoMapper 的映射规则。AutoMapper 是一个用于对象到对象映射的库,常用于将数据模型转换为视图模型或 DTO(数据传输对象)。以下是代码的主要功能和结构的详细解释:

1. 单例模式

GlobalConfigMapper 使用了单例模式,确保在整个应用程序中只有一个 GlobalConfigMapper 实例。通过 Lazy<T> 来延迟实例化,确保线程安全。

  • Lazy<GlobalConfigMapper> LazyMapper:使用 Lazy<T> 来延迟加载 GlobalConfigMapper 实例。
  • GetInstance()Instance 属性:提供获取单例实例的方法。

2. AutoMapper 配置

在构造函数中,调用 ConfigGlobalMapper() 方法来配置 AutoMapper 的映射规则,并将其赋值给 Mapper 属性。

3. 配置映射规则

ConfigGlobalMapper() 方法负责加载类型并配置映射规则。它执行以下步骤:

  • 加载类型:从 Dpz.Core.Public.ViewModel 程序集中获取所有导出的类型。
  • 配置 IMapFrom 接口映射:调用 ConfigureIMapFromMappings() 方法,处理实现了 IMapFrom<T> 接口的类型。
  • 配置静态接口映射:调用 ConfigureStaticInterfaceMappings() 方法,处理实现了 IHaveCustomMapping 接口的类型,并调用其静态方法 CreateMappings
  • 配置基于特性的映射:调用 ConfigureAttributeBasedMappings() 方法,处理带有 AutoMappingAttribute 特性的类型,并调用其 ConfigureMapping 方法。
  • 配置内置映射规则:调用 ConfigureBuiltInMappings() 方法,设置一些内置的映射规则,例如将 string 转换为 ObjectId

4. 映射配置方法

  • ConfigureIMapFromMappings:查找所有实现了 IMapFrom<T> 接口的类型,并为源类型和目标类型创建双向映射。
  • ConfigureStaticInterfaceMappings:查找所有实现了 IHaveCustomMapping 接口的类型,并调用其静态方法 CreateMappings 来配置映射。
  • ConfigureAttributeBasedMappings:查找所有带有 AutoMappingAttribute 特性的类型,并调用其 ConfigureMapping 方法来配置映射。
  • ConfigureBuiltInMappings:定义一些内置的映射规则,例如将字符串转换为 ObjectId

总结

GlobalConfigMapper 类的主要目的是集中管理 AutoMapper 的配置,提供灵活的映射规则,支持多种映射方式(接口、静态方法、特性等),并确保在整个应用程序中使用相同的映射配置。通过这种方式,开发人员可以轻松地进行对象之间的转换,减少手动映射的工作量。

loading