2013-07-16 19 views
8

Chcę wiedzieć, jak odwzorować pola dwóch różnych obiektów i przypisać do nich wartości.Jak odwzorować właściwości dwóch różnych obiektów?

procedury opisanej w przykładzie:

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

Teraz mam obiekt listy. Chcę przypisać wartości do klasy "manager". Dowolny automatyczny sposób na zrobienie tego. Mogę to zrobić jawnie i przypisać do niego wartości. Ale mój obiekt jest bardzo duży, to jest problem. Nie chcę też używać narzędzi innych firm.

Uwaga: nie może mieć żadnego przedrostka dla menedżera. To może być wszystko. (Przykład: mgrId może być podobny do mgrCode)

+4

* "Nie chcę używać żadnych narzędzi firm trzecich zbyt. "* Dlaczego nie? –

+2

Użyj refleksji http://msdn.microsoft.com/en-us/library/f7ykdhsy.aspx –

+5

Tylko sugestia: http://automapper.org/, jest to świetne narzędzie do konwersji takich obiektów. –

Odpowiedz

14

Można użyć refleksji do niego, nawet pomijając obudowę nieruchomości (zawiadomienie 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; } 
} 

Jeśli nie wiesz prefiks Mgr, można tylko mecz przyrostki:

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

i bardzo wąski i niepraktyczne założeniu,: odwzorowanie b w zamówieniu właściwości (jeśli oczekujesz, że 2 typy będą miały właściwości zdefiniowane w tej samej sekwencji i numerze, jedyną różnicą będą nazwy właściwości). Nie polecam nikomu używania go w prawdziwym życiu, ale mimo to jest tutaj (wystarczy aby uczynić go bardziej kruchy :)):

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

Istnieje przeciążenie ['PropertyInfo.GetValue'] (http://msdn.microsoft.com/en-us/library/hh194385.aspx), które przyjmuje obiekt źródłowy. Istnieje również przeciążenie dwóch argumentów ['PropertyInfo.SetValue'] (http://msdn.microsoft.com/en-us/library/hh194291.aspx). – Romoku

+0

Prawidłowe, zaczynając od 4.5. Kompilowałem z 3.5 :) Będę aktualizował moją odpowiedź. –

+0

Wydaje mi się, że ostatnio dużo korzystałem z .Net 4.5. – Romoku

10

Użyj refleksji lub AutoMapper. Polecam to drugie, ponieważ pisanie nowego kodu jest marnotrawstwem, jeśli nie ma celu.

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

Jeśli właściwości nie masz idiomatyczne identyfikator źródło następnie użyć AutoMapper na 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)) 
+0

Czy ignoruje obudowę nieruchomości? –

+0

Tak, to zignoruje obudowę nieruchomości. – Romoku

+0

Ale tutaj potrzebuję używać automappera. Czy jest jakikolwiek sposób na serializację? – Murugavel

Powiązane problemy