使用 Automapper 深度克隆对象,无法排除列表 <abstractBaseClass> 属性 中对象的 ID 属性
Deep cloning an object with Automapper, can't exclude Id property on objects in a List<abstractBaseClass> property
我有以下 classes:
public abstract class Question : IQuestion
{
[Key]
public int Id { get; set; }
// Some other base properties here
}
public class TextQuestion : Question
{
// Some class-specific properties here
}
还有一个 class 这样的:
public class SomeCompositeClass
{
[Key]
public int Id { get; set; }
// Some properties go here ...
public virtual List<Question> Questions { get; set; }
}
我想创建 SomeCompositeClass
的深层克隆,使用 Automapper(请不要建议 ICloneable
),但没有所有 ID,因为我会将其插入数据库,我使用 EntityFramework、存储库模式访问。
当然,我创建一个映射:
Mapper.CreateMap<SomeCompositeClass, SomeCompositeClass>().ForMember(rec => rec.Id, opt => opt.Ignore())
这对 SomeCompositeClass
非常有用。
但是我对问题 属性 做同样的事情时遇到了问题!问题出在列表中的基数class是abstract
,不是因为列表本身是virtual
,我已经排除了。
如果我创建 Mapper.CreateMap<Question, Question>()
或 Mapper.CreateMap<IQuestion, IQuestion>()
映射,代码会在运行时抛出异常,抱怨它无法创建抽象 (Question
) 对象的实例。
我试过 Mapper.CreateMap<List<Question>, List<Question>>()
,但这只会在运行时给我一个空的 Questions
列表。
我已经尝试创建特定问题的映射(TextQuestion
到 TextQuestion
),但它们没有启动,因为 Questions
属性 中的对象包裹在 EF 的 DynamicProxy
classes.
中
在 Mapper.Map(...) 期间,我该怎么做才能将 Id 从我的抽象基础 Question
class 的继承者中排除?
我是这样解决的:
首先,我更新到Automapper 4.1.1。那么:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Question, Question>()
.Include<TextBoxQuestion, TextBoxQuestion>()
// Supposedly inheritance mapping?
.ForMember(rec => rec.Id, opt => opt.Ignore());
cfg.CreateMap<TextBoxQuestion, TextBoxQuestion>()
// But either I don't understand inheritance mapping or it doesn't work, soI have to do that too
.ForMember(rec => rec.Id, opt => opt.Ignore());
cfg.CreateMap<SomeCompositeClass, SomeCompositeClass>()
.ForMember(rec => rec.Id, opt => opt.Ignore())
}
...
Mapper.Map(source, destination);
而且有效...
所以我认为我最缺少的是 .Include
部分,它告诉 Automapper 寻找最派生的 class.
我有以下 classes:
public abstract class Question : IQuestion
{
[Key]
public int Id { get; set; }
// Some other base properties here
}
public class TextQuestion : Question
{
// Some class-specific properties here
}
还有一个 class 这样的:
public class SomeCompositeClass
{
[Key]
public int Id { get; set; }
// Some properties go here ...
public virtual List<Question> Questions { get; set; }
}
我想创建 SomeCompositeClass
的深层克隆,使用 Automapper(请不要建议 ICloneable
),但没有所有 ID,因为我会将其插入数据库,我使用 EntityFramework、存储库模式访问。
当然,我创建一个映射:
Mapper.CreateMap<SomeCompositeClass, SomeCompositeClass>().ForMember(rec => rec.Id, opt => opt.Ignore())
这对 SomeCompositeClass
非常有用。
但是我对问题 属性 做同样的事情时遇到了问题!问题出在列表中的基数class是abstract
,不是因为列表本身是virtual
,我已经排除了。
如果我创建 Mapper.CreateMap<Question, Question>()
或 Mapper.CreateMap<IQuestion, IQuestion>()
映射,代码会在运行时抛出异常,抱怨它无法创建抽象 (Question
) 对象的实例。
我试过 Mapper.CreateMap<List<Question>, List<Question>>()
,但这只会在运行时给我一个空的 Questions
列表。
我已经尝试创建特定问题的映射(TextQuestion
到 TextQuestion
),但它们没有启动,因为 Questions
属性 中的对象包裹在 EF 的 DynamicProxy
classes.
在 Mapper.Map(...) 期间,我该怎么做才能将 Id 从我的抽象基础 Question
class 的继承者中排除?
我是这样解决的:
首先,我更新到Automapper 4.1.1。那么:
Mapper.Initialize(cfg =>
{
cfg.CreateMap<Question, Question>()
.Include<TextBoxQuestion, TextBoxQuestion>()
// Supposedly inheritance mapping?
.ForMember(rec => rec.Id, opt => opt.Ignore());
cfg.CreateMap<TextBoxQuestion, TextBoxQuestion>()
// But either I don't understand inheritance mapping or it doesn't work, soI have to do that too
.ForMember(rec => rec.Id, opt => opt.Ignore());
cfg.CreateMap<SomeCompositeClass, SomeCompositeClass>()
.ForMember(rec => rec.Id, opt => opt.Ignore())
}
...
Mapper.Map(source, destination);
而且有效...
所以我认为我最缺少的是 .Include
部分,它告诉 Automapper 寻找最派生的 class.