views:

174

answers:

3

I have two objects that contain some properties that are exactly the same (same name, type). What I want to do is populate one object's identical properties with another object's properties. I am trying to do this in code, but it's not working. The Bin object's properties are not being set.

class Basket{
    public Basket(int itemId, int itemGroup){
        ItemId=itemId;
        ItemGroup=itemGroup;
    }
    private int _itemId;
    private int _itemGroup;
    public int ItemId{ get{return _itemId;} set{_itemId = value};}
    public int ItemGroup{ get{return _itemGroup;} set{_itemGroup = value};}
}

struct Bin{
    public string Name;
    private int _itemId;
    private int _itemGroup;
    public int ItemId{ get{return _itemId;} set{_itemId = value};}
    public int ItemGroup{ get{return _itemGroup;} set{_itemGroup = value};}
    public bool IsEmpty;
}

Basket basket = new Basket(1,1);
Bin bin = new Bin();

PropertyInfo[] basketPI = basket.GetType().GetProperties();
PropertyInfo[] binPI = bin.GetType().GetProperties();

foreach(PropertyInfo biPI in binPI){
    foreach(PropertyInfo baPI in basketPI){
     if(baPI.Name==biPI.Name){
      biPI.SetValue(bin,baPI.GetValue(basket,null),null));
     }
    }
}

I'm trying to get away from simply doing:

object1.ItemId = object2.ItemId;
object1.ItemGroup = object2.ItemGroup;

I'm also wondering if there is a more elegant way to do this?

EDIT: I shorthanded the classes; meant to have the get/set in there.

EDIT: Changed to struct from object. For some reason it doesn't like setting the struct's properties when I do this.

+1  A: 

The things you have defined in your classes are fields not properties, so they won't be listed by the GetProperties() method.

Try changing them to (for example):

public int ItemId { get; set; }

Assuming you are on .NET 3.0 or higher, otherwise:

private int _itemId;
public int ItemId
{
    get { return _itemId; }
    set { _itemId = value; }
}

I question what it is you are trying to do though? Inheritance may be an option to make it more elegant - factoring out the shared properties into a base class. But if there is only these two properties, what is wrong with the code that just directly copies the values?

Martin Harris
This is just a simple example, the objects I am really using have quite a bit of properties, and I would like to have the code handle it rather than writing all of them out.
Rorschach
+3  A: 

You could use AutoMapper which allows you to configure a map so that one object can be translated to another.

Blog post: http://www.lostechies.com/blogs/jimmy_bogard/archive/2009/01/22/automapper-the-object-object-mapper.aspx

Below is an example from AutoMapper's Projection page

public class CalendarEvent
{
    public DateTime EventDate { get; set; }
    public string Title { get; set; }
}

public class CalendarEventForm
{
    public DateTime EventDate { get; set; }
    public int EventHour { get; set; }
    public int EventMinute { get; set; }
    public string Title { get; set; }
}

// Model
var calendarEvent = new CalendarEvent
{
    EventDate = new DateTime(2008, 12, 15, 20, 30, 0),
    Title = "Company Holiday Party"
};

// Configure AutoMapper
Mapper.CreateMap<CalendarEvent, CalendarEventForm>()
    .ForMember(dest => dest.EventDate, opt => opt.MapFrom(src => src.EventDate.Date))
    .ForMember(dest => dest.EventHour, opt => opt.MapFrom(src => src.EventDate.Hour))
    .ForMember(dest => dest.EventMinute, opt => opt.MapFrom(src => src.EventDate.Minute));
// Perform mapping

CalendarEventForm form = Mapper.Map<CalendarEvent, CalendarEventForm>(calendarEvent);
form.EventDate.ShouldEqual(new DateTime(2008, 12, 15));
form.EventHour.ShouldEqual(20);
form.EventMinute.ShouldEqual(30);
form.Title.ShouldEqual("Company Holiday Party");
Jon Erickson
(for automapper)++
Wyatt Barnett
Does this only work in c#3.0? I'm working with C#2.0 and don't have the lamda capability.
Rorschach
A: 

I would consider making a object property instead and then do a clone to copy the values. This whole approach seem like a hack. What if the properties have different types?

You could also use and interface to define IAdressSupport to find supported items.

PersonB.Address=directcast( PersonA.Address.Clone, Address)

eschneider