Encapsulation of the TinyMapper Object Mapping Framework

2023年7月19日 66点热度 2人点赞 0条评论
内容目录

Recently, I used a TinyMapper object mapping framework, and I like its simplicity.
TinyMapper documentation link: http://tinymapper.net/

TinyMapper is extremely simple; it consists of just a static class:

TinyMapper.Bind<Person, PersonDto>();

var person = new Person
{
    Id = Guid.NewGuid(),
    FirstName = "John",
    LastName = "Doe",
};

var personDto = TinyMapper.Map<PersonDto>(person);

// with mapping members ignored and bind members with different names/types

TinyMapper.Bind<Person, PersonDto>(config =>
{
	config.Ignore(x => x.Id);
	config.Ignore(x => x.Email);
	config.Bind(source => source.LastName, target => target.Surname);
	config.Bind(target => source.Emails, typeof(List<string>));
});

var person = new Person
{
	Id = Guid.NewGuid(),
	FirstName = "John",
	LastName = "Doe",
	Emails = new List<string>{"support@tinymapper.net", "MyEmail@tinymapper.net"}
};

var personDto = TinyMapper.Map<PersonDto>(person);

However, it does not provide many methods out of the box, so I need to directly encapsulate it to create a configuration interface.

    public class Mapper
    {
        public void Bind<TSource, TTarget>()
        {
            TinyMapper.Bind<TSource, TTarget>();
        }

        public static void Bind(Type sourceType, Type targetType)
        {
            TinyMapper.Bind(sourceType, targetType);
        }

        public static void Bind<TSource, TTarget>(Action<IBindingConfig<TSource, TTarget>> config)
        {
            TinyMapper.Bind<TSource, TTarget>(config);
        }
    }
    /// <summary>
    /// Object mapping
    /// </summary>
    public interface IMapper
    {
        /// <summary>
        /// Object mapping
        /// </summary>
        void InitMapper(Mapper map);
    }

Then, in the required places:

    internal class DataSourceMapper : IMapper
    {
        public void InitMapper(Mapper map)
        {
            map.Bind<DataSourceEntity, DataSourceVO>();
            map.Bind<DataSourceVO, DataSourceEntity>();
        }
    }

Next, write an extension method to scan all assemblies and automatically add the mappings:

    internal static class MapperExtensions
    {
        public static void AddMapper(this IServiceCollection services)
        {
            var map = new Mapper();
            foreach (var assembly in AppDomain.CurrentDomain.GetAssemblies())
            {
                var assemblyName = assembly.GetName();
                if (assemblyName == null || string.IsNullOrEmpty(assemblyName.Name)) continue;
                if (assemblyName.Name.StartsWith("System") || assemblyName.Name.StartsWith("Microsoft")) continue;
                foreach (var type in assembly.GetTypes())
                {
                    if (type.GetInterfaces().Any(x=>x == typeof(IMapper)))
                    {
                        var mapper = Activator.CreateInstance(type) as IMapper;
                        if(mapper == null)
                        {
                            Debug.Assert(mapper == null);
                            continue;
                        }
                        // Initialize the Mapper relationship
                        mapper.InitMapper(map);
                    }
                }
            }
        }
    }

痴者工良

高级程序员劝退师

文章评论