Best Practices for mapping one object to another

前端 未结 4 886
后悔当初
后悔当初 2020-12-02 15:40

My question is, what is the best way I can map one object to another in the most maintainable manner. I cannot change the way the Dto object that we are getting is setup to

相关标签:
4条回答
  • 2020-12-02 16:06

    This is a possible generic implementation using a bit of reflection (pseudo-code, don't have VS now):

    public class DtoMapper<DtoType>
    {
        Dictionary<string,PropertyInfo> properties;
    
        public DtoMapper()
        {
            // Cache property infos
            var t = typeof(DtoType);
            properties = t.GetProperties().ToDictionary(p => p.Name, p => p);
         }
    
        public DtoType Map(Dto dto)
        {
            var instance = Activator.CreateInstance(typeOf(DtoType));
    
            foreach(var p in properties)
            {
                p.SetProperty(
                    instance, 
                    Convert.Type(
                        p.PropertyType, 
                        dto.Items[Array.IndexOf(dto.ItemsNames, p.Name)]);
    
                return instance;
            }
        }
    

    Usage:

    var mapper = new DtoMapper<Model>();
    var modelInstance = mapper.Map(dto);
    

    This will be slow when you create the mapper instance but much faster later.

    0 讨论(0)
  • 2020-12-02 16:11

    I would opt for AutoMapper, an open source and free mapping library which allows to map one type into another, based on conventions (i.e. map public properties with the same names and same/derived/convertible types, along with many other smart ones). Very easy to use, will let you achieve something like this:

    Model model = Mapper.Map<Model>(dto);
    

    Not sure about your specific requirements, but AutoMapper also supports custom value resolvers, which should help you writing a single, generic implementation of your particular mapper.

    0 讨论(0)
  • 2020-12-02 16:13
    /// <summary>
    /// map properties
    /// </summary>
    /// <param name="sourceObj"></param>
    /// <param name="targetObj"></param>
    private void MapProp(object sourceObj, object targetObj)
    {
        Type T1 = sourceObj.GetType();
        Type T2 = targetObj.GetType();
    
        PropertyInfo[] sourceProprties = T1.GetProperties(BindingFlags.Instance | BindingFlags.Public);
        PropertyInfo[] targetProprties = T2.GetProperties(BindingFlags.Instance | BindingFlags.Public);
    
       foreach (var sourceProp in sourceProprties)
       {
           object osourceVal = sourceProp.GetValue(sourceObj, null);
           int entIndex = Array.IndexOf(targetProprties, sourceProp);
           if (entIndex >= 0)
           {
               var targetProp = targetProprties[entIndex];
               targetProp.SetValue(targetObj, osourceVal);
           }
       }
    }
    
    0 讨论(0)
  • 2020-12-02 16:18

    Efran Cobisi's suggestion of using an Auto Mapper is a good one. I have used Auto Mapper for a while and it worked well, until I found the much faster alternative, Mapster.

    Given a large list or IEnumerable, Mapster outperforms Auto Mapper. I found a benchmark somewhere that showed Mapster being 6 times as fast, but I could not find it again. You could look it up and then, if it is suits you, use Mapster.

    0 讨论(0)
提交回复
热议问题