简体   繁体   中英

Automapper: binding a concrete class “from” multiple interface

I'm tring to map a class (TrackingKeyStatic) using c# and automapper. TrackingKeyStatic has the interface IBatchProcessing is herited from Trackingkey wich has the interface ITrackingKey. So by definition TrackingKeyStatic is IBatchProcessing and ITrackingKey.

Automapper working fine with only one interface (IBatchProcessing) But can't be mapped/be detect with interface ITrackingKey

I've created a fiddle to demonstrate https://dotnetfiddle.net/TO21PI

So the question is how can I map source with two interface to a croncrete type?

  • i've tried with this config, and it didnt work (wich is the problème)

      cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>() 
  • I've tried to change the automapper config for

      cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>() 

    As demonstrate in Method TestWitTrackingKeyStaticAsSource_WORKING() its working just fine. But I can't really make a mappingf for each subclass

  • I've tried to use method like .Include or .IncludeAllDerived, it didn't work, but i'm not quite sure if I need to use them here? Maybe I did it wrong?

Heres the unit tests I wrote for this question

using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;

namespace StackOverflow
{
    [TestClass]
    public class UnitTest1
    {
        [TestMethod]
        public void TestWithItrackingAsSource_NOTWORKING()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>()
                    .ForMember(d => d.TrackingKey, o => o.MapFrom(s => s.NewTrackingKey));
                cfg.CreateMap<IBatchProcessing, MyEntitiesDbFirstModel>()
                    .ForMember(d => d.Skip, o => o.MapFrom(s => s.Skip))
                    .ForMember(d => d.Take, o => o.MapFrom(s => s.Take))
                    .ForMember(d => d.Total, o => o.MapFrom(s => s.Total));
            });
            var mapper = config.CreateMapper();
            var source = new TrackingKeyStatic<NotReleventClassForThisExample>()
            {
                Skip = 10,
                Take = 50,
                Total = 123456,
                NewTrackingKey = 987654
            };
            var actual = mapper.Map<MyEntitiesDbFirstModel>(source);
            Assert.AreEqual(10, actual.Skip);//ok
            Assert.AreEqual(50, actual.Take);//ok
            Assert.AreEqual(123456, actual.Total);//ok
            Assert.AreEqual(987654, actual.TrackingKey);//failed
        }

        [TestMethod]
        public void TestWitTrackingKeyStaticAsSource_WORKING()
        {
            var config = new MapperConfiguration(cfg => {
                cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>()
                    .ForMember(d => d.TrackingKey, o => o.MapFrom(s => s.NewTrackingKey));
                cfg.CreateMap<IBatchProcessing, MyEntitiesDbFirstModel>()
                    .ForMember(d => d.Skip, o => o.MapFrom(s => s.Skip))
                    .ForMember(d => d.Take, o => o.MapFrom(s => s.Take))
                    .ForMember(d => d.Total, o => o.MapFrom(s => s.Total));
            });
            var mapper = config.CreateMapper();
            var source = new TrackingKeyStatic<NotReleventClassForThisExample>()
            {
                Skip = 10,
                Take = 50,
                Total = 123456,
                NewTrackingKey = 987654
            };
            var actual = mapper.Map<MyEntitiesDbFirstModel>(source);
            Assert.AreEqual(10, actual.Skip);//ok
            Assert.AreEqual(50, actual.Take);//ok
            Assert.AreEqual(123456, actual.Total);//ok
            Assert.AreEqual(987654, actual.TrackingKey);//work fine
        }
    }
    public interface ITrackingKey
    {
        int NewTrackingKey { get; set; }
        List<object> Records { get; set; }
    }
    public interface IBatchProcessing
    {
        int Skip { get; set; }
        int Take { get; set; }
        int Total { get; set; }
    }
    public class TrackingKey<T> : ITrackingKey
    {
        private List<object> _records;

        public int NewTrackingKey { get; set; }

        public List<T> Records  //not relevent for question, it just for implementing interface
        {
            get { return _records?.Cast<T>()?.ToList(); }
            set { _records = value?.Cast<object>()?.ToList(); }
        }

        List<object> ITrackingKey.Records //not relevent for question, it just for implementing interface
        {
            get { return _records; }
            set { _records = value; }
        }
    }
    public class TrackingKeyStatic<T> : TrackingKey<T>, IBatchProcessing
    {
        public int Skip { get; set; }
        public int Take { get; set; }
        public int Total { get; set; }
    }
    public class MyEntitiesDbFirstModel
    {
        public int Skip { get; set; }
        public int Take { get; set; }
        public int Total { get; set; }
        public int TrackingKey { get; set; }
    }

    public class NotReleventClassForThisExample { public int MyProperty { get; set; }}
}

I was able to get it working with a small "hacky" wrapper method:

    public static MyEntitiesDbFirstModel MapToMyDbModel<T>(TrackingKeyStatic<T> trackingKey, IMapper mapper)
    {
        var interimTypeObject = new TrackingKey<T>()
        {
            NewTrackingKey = trackingKey.NewTrackingKey
        };

        var actual = mapper.Map<MyEntitiesDbFirstModel>(trackingKey);
        mapper.Map<ITrackingKey, MyEntitiesDbFirstModel>(interimTypeObject, actual);

        return actual;
    }   

Here's the fiddle for it - https://dotnetfiddle.net/XAjQB4

You may be able get rid of uglyness further - it seems that AutoMapper is not able to choose the correct map here when you use TrackingKeyStatic<T> but has no problems doing TrackingKey<T> .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM