Domanda

La classe di origine:

public class Post
{
    public long ID { get; set; }

    [Column(TypeName="nvarchar")]
    [Required]
    [StringLength(250)]
    public string Name { get; set; }

    [Column(TypeName="varchar")]
    [StringLength(250)]
    public string UrlName { get; set; }

    [Column(TypeName="ntext")]
    public string Excerpt { get; set; }

    [Column(TypeName="ntext")]
    [Required]
    public string Content { get; set; }

    public DateTime PostedTime { get; set; }
    public DateTime? PublishedTime { get; set; }
    public DateTime? LastUpdatedTime { get; set; }
    public bool IsPublished { get; set; }

    public virtual List<Category> Categories { get; set; }
    public virtual List<Comment> Comments { get; set; }
    public virtual List<Tag> Tags { get; set; }
}

la classe di destinazione

public class Post : Model
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string UrlName { get; set; }
    public string Excerpt { get; set; }
    public string Content { get; set; }
    public DateTime PostedTime { get; set; }
    public DateTime LastCommentedTime { get; set; }
    public bool IsPublished { get; set; }

    public List<Category> Category { get; set; }
    public List<Comment> Comments { get; set; }
    public List<Tag> Tags { get; set; }
}

cerco usando EmitMapper per mappare gli uni dagli altri; quando la mappatura dalla sorgente alla desction, ecco il codice di esempio:

[TestMethod]
    public void ShouleMapEntityToModel()
    {
        Post eP = new Post();
        eP.ID = 2;
        eP.Comments = new List<Comment>();

        eP.Comments.Add(new Comment()
            {
                ID = 2,
                Author = "derek"
            });

        var mP = eP.Map<Post, mBlog.Core.Models.Post>();

        Assert.IsNotNull(mP);
        Assert.AreEqual(1, mP.Comments.Count());
    }

ed ho ottenuto un'eccezione,

Metodo di prova mBlog.Test.EmitMapperTest.ShouleMapEntityToModel ha gettato un'eccezione: System.Exception: costruzione per tipi [] non trovata in System.Collections.Generic.IList`1 [[mBlog.Core.Models.Post, mBlog.Core, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]]

È stato utile?

Soluzione

Ho avuto lo stesso problema, ma ho trovato la soluzione. Non elenchi di utenti per l'oggetto di destinazione. Se si utilizzano gli array semplici nell'oggetto mBlog.Core.Models.Post si dovrebbe ottenere un oggetto ben riempita. Così la vostra classe di destinazione dovrebbe essere simile:

public class Post : Model
{
    public long ID { get; set; }
    public string Name { get; set; }
    public string UrlName { get; set; }
    public string Excerpt { get; set; }
    public string Content { get; set; }
    public DateTime PostedTime { get; set; }
    public DateTime LastCommentedTime { get; set; }
    public bool IsPublished { get; set; }

    public Category[] Category { get; set; }
    public Comment[] Comments { get; set; }
    public Tag[] Tags { get; set; }
}

Altri suggerimenti

questa risposta mostra come gestire IEnumerable a IEnumerable: EmitMapper e Lista

Credo che può essere applicato a questo caso. Date un'occhiata:

Questo può essere fatto creando una classe personalizzata, che implementa l'interfaccia "ICustomConverterProvider" e l'aggiunta di un ConvertGeneric al "DefaultMapConfig".

Guardando sul codice sorgente di EmitMapper, ho trovato una classe denominata "ArraysConverterProvider", che è il convertitore generico di default da ICollections ad array.

L'adattamento del codice da questa classe di lavorare con IEnumerable collezioni:

class GenericIEnumerableConverterProvider : ICustomConverterProvider
    {
      public CustomConverterDescriptor GetCustomConverterDescr(
            Type from,
            Type to,
            MapConfigBaseImpl mappingConfig)
        {
            var tFromTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(from);
            var tToTypeArgs = DefaultCustomConverterProvider.GetGenericArguments(to);
            if (tFromTypeArgs == null || tToTypeArgs == null || tFromTypeArgs.Length != 1 || tToTypeArgs.Length != 1)
            {
                return null;
            }
            var tFrom = tFromTypeArgs[0];
            var tTo = tToTypeArgs[0];
            if (tFrom == tTo && (tFrom.IsValueType || mappingConfig.GetRootMappingOperation(tFrom, tTo).ShallowCopy))
           {
               return new CustomConverterDescriptor
                {
                    ConversionMethodName = "Convert",
                    ConverterImplementation = typeof(GenericIEnumerableConverter_OneTypes<>),
                    ConverterClassTypeArguments = new[] { tFrom }
                };
            }

            return new CustomConverterDescriptor
            {
                ConversionMethodName = "Convert",
                ConverterImplementation = typeof(GenericIEnumerableConverter_DifferentTypes<,>),
                ConverterClassTypeArguments = new[] { tFrom, tTo }
            }; 
        }
    }


class GenericIEnumerableConverter_DifferentTypes<TFrom, TTo> : ICustomConverter
    {
        private Func<TFrom, TTo> _converter;
        public IEnumerable<TTo> Convert(IEnumerable<TFrom> from, object state)
        {
            if (from == null)
            {
                return null;
            } 

            TTo[] result = new TTo[from.Count()];
            int idx = 0;
            foreach (var f in from)
            {
                result[idx++] = _converter(f);
            }

            return result;
        } 

        public void Initialize(Type from, Type to, MapConfigBaseImpl mappingConfig)
        {
            var staticConverters = mappingConfig.GetStaticConvertersManager() ?? StaticConvertersManager.DefaultInstance;

            var staticConverterMethod = staticConverters.GetStaticConverter(typeof(TFrom), typeof(TTo));

           if (staticConverterMethod != null)
            {
                _converter = (Func<TFrom, TTo>)Delegate.CreateDelegate(
                    typeof(Func<TFrom, TTo>),
                    null,
                    staticConverterMethod
                );
            }
            else
            {
                _subMapper = ObjectMapperManager.DefaultInstance.GetMapperImpl(typeof(TFrom), typeof(TTo), mappingConfig);

                _converter = ConverterBySubmapper;
            }
        } 

        ObjectsMapperBaseImpl _subMapper;

        private TTo ConverterBySubmapper(TFrom from)
        {
            return (TTo)_subMapper.Map(from);
        }
    }


class GenericIEnumerableConverter_OneTypes<T>
    {

        public IEnumerable<T> Convert(IEnumerable<T> from, object state)
        {
            if (from == null)
          {
                return null;
            }

            return from;
        }
    }

Questo codice è solo una copia con un minimo di adattamento possibile e può essere applyed di oggetti con molti livelli di gerarchia.

È possibile utilizzare il codice precedente con il seguente comando:

  new DefaultMapConfig().ConvertGeneric(
    typeof(IEnumerable<>),
    typeof(IEnumerable<>),
    new GenericIEnumerableConverterProvider());

Questo mi ha salvato la giornata e spero di salvare anche il vostro! hehehe

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top