如何映射两个不同对象的属性

本文关键字:属性 两个 对象 何映射 映射 | 更新日期: 2023-09-27 18:22:38

我想知道如何映射两个不同对象的字段并为其赋值。

Eample:

public class employee
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class manager
{
    public int MgrId { get; set; }
    public string MgrName { get; set; }
}

现在我有了一个List对象。我想将值分配给"manager"类。任何自动的方法。我可以显式地做,并为它赋值。但我的对象非常大,这就是问题所在。我也不想使用任何第三方工具。

注意:它不能有任何manager前缀。它可以是任何东西。(例如:mgrId可以类似于mgrCode)

如何映射两个不同对象的属性

您可以使用反射,甚至可以忽略属性大小写(注意employee.IDmanager.MgrId):

class Program
{
    static void Main(string[] args)
    {
        var employee = new Employee() { ID = 1, Name = "John" };
        var manager = new Manager();
        foreach (PropertyInfo propertyInfo in typeof(Employee).GetProperties())
        {
            typeof(Manager)
                .GetProperty("Mgr" + propertyInfo.Name,
                    BindingFlags.IgnoreCase |
                    BindingFlags.Instance |
                    BindingFlags.Public)
                .SetValue(manager,
                    propertyInfo.GetValue(employee));
        }
    }
}
public class Employee
{
    public int ID { get; set; }
    public string Name { get; set; }
}
public class Manager
{
    public int MgrId { get; set; }
    public string MgrName { get; set; }
}

如果你不知道Mgr前缀,你只能通过后缀进行匹配:

foreach (PropertyInfo propertyInfo in typeof(Employee).GetProperties())
{
    typeof(Manager).GetMembers()
        .OfType<PropertyInfo>()
        .FirstOrDefault(p => p.Name.EndsWith(propertyInfo.Name, 
            StringComparison.CurrentCultureIgnoreCase))
        .SetValue(manager,
            propertyInfo.GetValue(employee));
}

是一个非常狭窄且不切实际的假设:基于属性顺序的映射(如果您希望这两种类型的属性定义在相同的序列和编号中,唯一的区别是属性名称)。我不建议任何人在现实生活中使用它,但它仍然在这里(只是为了让它更脆弱:):

typeof(Employee)
    .GetProperties()
    .Select((p, index) =>
        new { Index = index, PropertyInfo = p })
    .ToList()
    .ForEach(p =>
        {
            typeof(Manager)
                .GetProperties()
                .Skip(p.Index)
                .FirstOrDefault()
                .SetValue(manager,
                    p.PropertyInfo.GetValue(employee));
        });

使用反射或AutoMapper。我推荐后者,因为如果没有目的,编写新代码是浪费。

public class Employee
{
    public int Id { get; set; }
    public string Name { get; set; }
}
public class Manager
{
    public int MgrId { get; set; }
    public string MgrName { get; set; }
}
Mapper.Initialize(cfg =>
{
   cfg.RecognizeDestinationPrefixes("Mgr");
   cfg.CreateMap<Employee, Manager>();
});
var manager = Mapper.Map<Employee, Manager>(new Employee { Id = 1, Name = "Fred" });
Console.WriteLine("Id: {0}", manager.MgrId);
Console.WriteLine("Name: {0}", manager.MgrName);

如果属性没有惯用的源标识符,则使用AutoMapper的投影。

Mapper.CreateMap<Employee, Manager>()
      .ForMember(dest => dest.MgrCode, opt => opt.MapFrom(src => src.ID))
      .ForMember(dest => dest.MgrName, opt => opt.MapFrom(src => src.Name))

我知道这篇文章现在有点过时了,但对于其他正在寻找答案的人来说,这就是你可以追求的。。只需简单地使用lambda表达式

var managers = employees.Select(x => new Manager()
{
    MgrCode = x.ID,
    MgrName = x.Name
}).ToList();