编辑: 我在输入这个问题时意识到自己,通过使用泛型可以实现一个简单的解决方案。我正在测试它,并将很快发布...
给定两个实体类(例如,从数据库加载数据):
class PersonFromDb
{
public string NameFromDb { get; }
// ... other properties follow...
}
class ChildFromDb
{
public PersonFromDb Person { get; }
public int AgeFromDb { get; }
}
...以及下面的“目标”类,我想要映射:
class Person
{
public string Name{ get; set; }
}
class Child : Person
{
public int Age {get; set; }
}
现在说我已经编写了一种映射方法,用于将PersonFromDb
映射到Person
:
public Person MapPerson(PersonFromDb person){
return new Person {
Name = person.NameFromDb,
// ...
}
}
另一种映射Child的方法:
public Child MapChild(ChildFromDb child){ ... }
我想在此处执行的操作是映射到MapPerson()
内的MapChild()
,以避免重新映射所有常见属性。
我不能将MapPerson()
与Child
一起使用,因为它会返回Person
,而不是Child
。
有没有任何模式可以帮我解决这个问题,所以我不必在这里重复这么多的映射逻辑?
答案 0 :(得分:1)
正如我的编辑中提到的,我在写这个问题时意识到使用泛型有一个简单的解决方案:
public T MapPerson<T>(PersonFromDb person) where T : Person, new() {
return new T {
Name = person.NameFromDb,
// ...
}
}
这将允许以下两种情况:
Person mappedPerson = MapPerson<Person>(instanceOfPersonFromDb);
Child mappedChild = MapPerson<Child>(instanceOfChildFromDb.Person);
然后,我可以从MapChild()
调用后者,允许我在MapPerson()
中映射公共属性,然后在Child
中添加MapChild()
中定义的额外属性
答案 1 :(得分:1)
您可以创建通用人物映射器,它将创建并映射任何具有无参数构造函数的人员类型:
public <TPerson> MapPerson<TPerson>(PersonFromDb dbPerson){
where TPerson: Person, new()
return new TPerson {
Name = dbPerson.NameFromDb,
// ...
}
}
然后使用此通用人物映射器来映射孩子:
public Child MapChild(ChildFromDb dbChild)
{
var child = MapPerson<Child>(dbChild.Person);
child.Age = dbChild.AgeFromDb;
return child;
}
答案 2 :(得分:0)
您可以依靠像AutoMapper这样的映射框架来完成这项工作。
另一种解决方案可能是使用接口而不是继承。定义一个由Person et Child对象实现的IPerson接口。然后你的MapPerson函数可能像MapPerson(IPerson目标,PersonFromDb源)那样初始化目标对象,因此能够初始化Person或Child对象。
或者您可以使用组合而不是继承,并使Person对象成为子对象的属性。