Question

La classe source:

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 de destination

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; }
}

J'essayer d'utiliser EmitMapper à la carte de l'autre; lorsque la cartographie de la source à desction, voici l'exemple de code:

[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());
    }

et je suis une exception,

Méthode d'essai mBlog.Test.EmitMapperTest.ShouleMapEntityToModel jeta exception: System.Exception: Constructor pour les types [] ne se trouve pas dans System.Collections.Generic.IList`1 [[mBlog.Core.Models.Post, mBlog.Core, Version = 1.0.0.0, Culture = neutral, PublicKeyToken = null]]

Était-ce utile?

La solution

J'ai eu le même problème, mais je l'ai trouvé la solution. Ne pas Listes d'utilisateurs pour votre objet de destination. Si vous utilisez des tableaux simples dans votre objet mBlog.Core.Models.Post vous devriez obtenir un objet bien rempli. Donc, votre classe de destination devrait ressembler à:

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; }
}

Autres conseils

Cette réponse montre comment gérer IEnumerable IEnumerable: EmitMapper et liste

Je crois que peut être appliquée à ce cas aussi. Jetez un coup d'oeil:

Cela peut être fait de créer une classe personnalisée, mise en œuvre de l'interface « ICustomConverterProvider » et en ajoutant un ConvertGeneric au « DefaultMapConfig ».

Recherche sur le code source de EmitMapper, je l'ai trouvé une classe nommée « ArraysConverterProvider », qui est la valeur par défaut convertisseur générique de ICollections aux tableaux.

L'adaptation du code de cette classe pour travailler avec IEnumerable collections:

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;
        }
    }

Ce code est juste une copie avec un minimum d'adaptation possible et peut être applyed à des objets avec de nombreux niveaux de la hiérarchie.

Vous pouvez utiliser le code ci-dessus avec la commande suivante:

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

Cela a sauvé ma journée et j'espère vôtre sauver aussi! hehehe

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top