简体   繁体   English

AutoMapper开放泛型映射不起作用

[英]AutoMapper Open Generics Mapping Not Working

I am trying to setup a map to utilize open generics, but it never works at runtime. 我正在尝试设置一个映射以利用开放的泛型,但是它在运行时永远无法工作。 I'm using AutoMapper 5.2 in .NET Core. 我在.NET Core中使用AutoMapper 5.2。

I have these models: 我有以下模型:

public interface IRestData<T>
{
    T Data { get; }
    IPaging Paging { get; }

    void SetData(T data);
    void SetPaging(IPaging paging);
}

public interface IPaging
{
    int Count { get; }

    void SetCount(int count);
}

public class RestData<T> : IRestData<T>
{
    T _data;
    IPaging _paging = new Paging(0);

    public RestData() {}

    public RestData(T data)
    {
        _data = data;

        if (!typeof(IEnumerable).GetTypeInfo()
                                .IsAssignableFrom(typeof(T)))
            _paging = new Paging(data != null
                                     ? 1
                                     : 0);
    }

    public RestData(T data, IPaging paging)
    {
        _data = data;
        _paging = paging;
    }

    public T Data => _data;
    public IPaging Paging => _paging;

    public void SetData(T data) => _data = data;
    public void SetPaging(IPaging paging) => _paging = paging;
}

public class Paging : IPaging
{
    int _count;

    public Paging() {}

    public Paging(int count)
    {
        _count = count;
    }

    public int Count => _count;
    public void SetCount(int count) => _count = count;
}

I want to be able to Map from one RestData<T> to another RestData<T> where T is not necessarilly the same. 我希望能够从一个RestData <T>映射到另一个RestData <T>,其中T不必相同。 I create an AutoMapper.Profile that looks like this (using interface): 我创建一个如下所示的AutoMapper.Profile(使用界面):

public class CommonProfile : Profile
{
    public CommonProfile()
    {
        CreateMap(typeof(IRestData<>), typeof(IRestData<>))
            .ConvertUsing(typeof(RestDataConverter<,>));
    }
}

I also tried it like this (using concrete type): 我也这样尝试过(使用具体类型):

public class CommonProfile : Profile
{
    public CommonProfile()
    {
        CreateMap(typeof(RestData<>), typeof(RestData<>))
            .ConvertUsing(typeof(RestDataConverter<,>));
    }
}

This is what my RestDataConverter looks like: 这是我的RestDataConverter的样子:

public class RestDataConverter<TSource, TDestination> : ITypeConverter<IRestData<TSource>, IRestData<TDestination>>
{
    public IRestData<TDestination> Convert(IRestData<TSource> source, IRestData<TDestination> destination, ResolutionContext context)
    {
        destination = destination ?? new RestData<TDestination>();
        destination.SetData(context.Mapper.Map<TDestination>(source.Data));
        destination.SetPaging(source.Paging);
        return destination;
    }
}

I'm trying to map between two collections of specific object types (source: RestData<List<DocumentRecord>>, dest: RestData<List<Document>>). 我正在尝试在特定对象类型的两个集合之间进行映射(源:RestData <List <DocumentRecord >>,目标:RestData <List <Document >>)。 Here are my model types: 这是我的模型类型:

public class DocumentRecord
{
    public DateTime CreatedTs { get; set; }
    public int DocumentId { get; set; }
    public long FileSize { get; set; }
    public DateTime LastUpdatedTs { get; set; }
    public int NumberOfPages { get; set; }
    public string OriginalFileName { get; set; }
    public IList<PageGroupRecord> PageGroups { get; set; } = new List<PageGroupRecord>();
    public string Type { get; set; }
}

public class Document
{
    public int ConfigurationId { get; set; }
    public DateTime CreatedTs { get; set; }
    public int DocumentId { get; set; }
    public string FileLocation { get; set; }
    public int FileSize { get; set; }
    public DateTime LastUpdatedTs { get; set; }
    public int NumberOfPages { get; set; }
    public string OriginalFileName { get; set; }
    public IList<PageGroup> PageGroups { get; set; } = new List<PageGroup>();
    public string Type { get; set; }
}

And here is the AutoMapper.Profile for these two object types: 这是这两种对象类型的AutoMapper.Profile:

public class ServicesProfile : Profile
{
    public ServicesProfile()
    {
        CreateMap<Document, DocumentRecord>()
            .ForMember(_ => _.Configuration, _ => _.Ignore())
            .ReverseMap();
    }
}

I am loading profiles in Startup.cs: 我正在Startup.cs中加载配置文件:

public void ConfigureServices(IServiceCollection services)
{
    var mapperConfiguration = new MapperConfiguration(_ =>
                                                    {
                                                        _.AddProfile<CommonProfile>();
                                                        _.AddProfile<ServicesProfile>();
                                                    });
    services.AddSingleton(mapperConfiguration);
    services.AddSingleton(mapperConfiguration.CreateMapper());
}

Whenever I do a map I get this exception: 每当我制作地图时,都会出现此异常:

Unable to cast object of type 'RestDataConverter`2[System.Collections.Generic.List`1[DocumentRecord],System.Collections.Generic.List`1[Document]]' to type 'AutoMapper.ITypeConverter`2[RestData`1[System.Collections.Generic.List`1[DocumentRecord]],RestData`1[System.Collections.Generic.List`1[Document]]]'.

Furthermore, when I try to do something more simple (source: RestData<int>, dest: RestData<int>) such as this unit test, I get a similar exception: 此外,当我尝试执行更简单的操作(源:RestData <int>,dest:RestData <int>)(例如此单元测试)时,我得到了类似的异常:

public class CommonProfileTests : BaseTests
{
    static CommonProfileTests()
    {
        Mapper.Initialize(m => m.AddProfile<CommonProfile>());
    }

    // This unit test passes
    [Fact]
    public void Configuration_Is_Valid() => AssertConfigurationIsValid();

    // This unit test fails with the error below
    [Fact]
    public void RestData_Maps_To_RestData_Correctly()
    {
        var source = new RestData<int>(1, new Paging(4));

        var destination = Map<RestData<int>>(source);

        Assert.Equal(source.Data, destination.Data);
    }
}

Same basic exception: 相同的基本例外:

Unable to cast object of type 'RestDataConverter`2[System.Int32,System.Int32]' to type 'AutoMapper.ITypeConverter`2[RestData`1[System.Int32],RestData`1[System.Int32]]'.

I figured out what the issue was. 我弄清楚了问题所在。 My RestDataConverter was using the interface types instead of the concrete types. 我的RestDataConverter使用的是接口类型,而不是具体类型。 When I changed to using the concrete RestData<T>, it suddendly started working fine. 当我改为使用具体的RestData <T>时,它突然开始正常工作。

public class RestDataConverter<TSource, TDestination> : ITypeConverter<RestData<TSource>, RestData<TDestination>>
{
    public RestData<TDestination> Convert(RestData<TSource> source, RestData<TDestination> destination, ResolutionContext context)
    {
        destination = destination ?? new RestData<TDestination>();
        destination.SetData(context.Mapper.Map<TDestination>(source.Data));
        destination.SetPaging(source.Paging);
        return destination;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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