How to map properties of two different objects?

2020-02-09 04:40发布

问题:

I want to know how to map fields of two different objects and assign the values to it.

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; }
}

Now I have a List object. I want to assign the values to "manager" class. Any automatic way to do that. I can do it explicitly and assigning values to it. But my object is very huge thats the problem. I dont want to use any third party tools too.

Note: It can't have any prefix for manager. It can be anything. (Ex: mgrId can be like mgrCode)

回答1:

You could use reflection for it, even by ignoring the property casing (notice the employee.ID vs. manager.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; }
}

If you don't know the Mgr prefix, you could only match by suffixes:

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));
}

And a very narrow and impractical assumption: mapping based on the property order (if you are expecting the 2 types to have properties defined in the same sequence and number, the only difference being the property names). I wouldn't recommend anyone using it in real life, but still, here it is (just to make it more fragile :) ):

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));
        });


回答2:

Use reflection or AutoMapper. I recommend the latter since writing new code is wasteful if it doesn't have a purpose.

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);

If the properties don't have an idiomatic source identifier then use AutoMapper's projection.

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


标签: c# oop object