Automapper:绑定一个具体的class"from"多个接口
Automapper: binding a concrete class "from" multiple interface
我正在尝试使用 c# 和自动映射器映射 class (TrackingKeyStatic)。
TrackingKeyStatic 具有接口 IBatchProcessing 继承自具有接口 ITrackingKey 的 Trackingkey。
所以根据定义,TrackingKeyStatic 是 IBatchProcessing 和 ITrackingKey。
Automapper 仅使用一个接口即可正常工作 (IBatchProcessing)
但不能 mapped/be 检测接口 ITrackingKey
我创建了一个 fiddle 来演示 https://dotnetfiddle.net/TO21PI
所以问题是如何将具有两个接口的源映射到一个 croncrete 类型?
我试过这个配置,但没有用(这是问题所在)
cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>()
我已经尝试更改
的自动映射器配置
cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>()
正如方法 TestWitTrackingKeyStaticAsSource_WORKING() 中所展示的那样,它工作得很好。但是我真的不能为每个 subclass
做一个 mappingf
我试过使用.Include 或.IncludeAllDerived 之类的方法,它没有用,但我不太确定是否需要在这里使用它们?也许我做错了?
这是我为这个问题写的单元测试
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Whosebug
{
[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; }}
}
我能够使用一个小的 "hacky" 包装方法让它工作:
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;
}
这是 fiddle - https://dotnetfiddle.net/XAjQB4
您也许可以进一步摆脱丑陋 - 当您使用 TrackingKeyStatic<T>
时,AutoMapper 似乎无法在此处选择正确的地图,但在执行 TrackingKey<T>
.[=14 时没有问题=]
我正在尝试使用 c# 和自动映射器映射 class (TrackingKeyStatic)。 TrackingKeyStatic 具有接口 IBatchProcessing 继承自具有接口 ITrackingKey 的 Trackingkey。 所以根据定义,TrackingKeyStatic 是 IBatchProcessing 和 ITrackingKey。
Automapper 仅使用一个接口即可正常工作 (IBatchProcessing) 但不能 mapped/be 检测接口 ITrackingKey
我创建了一个 fiddle 来演示 https://dotnetfiddle.net/TO21PI
所以问题是如何将具有两个接口的源映射到一个 croncrete 类型?
我试过这个配置,但没有用(这是问题所在)
cfg.CreateMap<ITrackingKey, MyEntitiesDbFirstModel>()
我已经尝试更改
的自动映射器配置cfg.CreateMap<TrackingKeyStatic<NotReleventClassForThisExample>, MyEntitiesDbFirstModel>()
正如方法 TestWitTrackingKeyStaticAsSource_WORKING() 中所展示的那样,它工作得很好。但是我真的不能为每个 subclass
做一个 mappingf
我试过使用.Include 或.IncludeAllDerived 之类的方法,它没有用,但我不太确定是否需要在这里使用它们?也许我做错了?
这是我为这个问题写的单元测试
using System;
using System.Collections.Generic;
using System.Linq;
using AutoMapper;
using Microsoft.VisualStudio.TestTools.UnitTesting;
namespace Whosebug
{
[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; }}
}
我能够使用一个小的 "hacky" 包装方法让它工作:
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;
}
这是 fiddle - https://dotnetfiddle.net/XAjQB4
您也许可以进一步摆脱丑陋 - 当您使用 TrackingKeyStatic<T>
时,AutoMapper 似乎无法在此处选择正确的地图,但在执行 TrackingKey<T>
.[=14 时没有问题=]