2

I have Two Classes.

Class A:

public class A {
    prop string p1  { get; set; }
    prop string p2  { get; set; }
    prop string p3  { get; set; }
}

Class B:

public class B {
    prop string p1  { get; set; }
    prop string p3  { get; set; }
}

Now assume we have an object from class B and we want to assign it to object from class A.

B b_obj = new B(){
     p1 = "something",
     p2 = "something else"
} 

A a_obj = new A(){
    p1 = b_obj.p1,
    p3 = b_obj.p3,
}

I think the above solution is not best way.

What is best practice to assign b_obj to another object from class A?

Tip : All property in class B has a similar property in class A

  • You could create a copy constructor in `B` that takes an instance of `A`. But if all properties are similar the question arises why there are two classes at all – Tim Schmelter Mar 06 '17 at 10:04
  • 1
    @TimSchmelter - which will end up with same "mapping" logic – Fabio Mar 06 '17 at 10:04
  • 1
    This is called "object to object mapping". You can do this manually, or use third party solution like Automapper. – Dennis Mar 06 '17 at 10:04
  • 1
    For a broader solution, look at tools like AutoMapper – H H Mar 06 '17 at 10:04
  • 1
    @Fabio: sure, but only once and encapsulated in `B` not everywhere. – Tim Schmelter Mar 06 '17 at 10:06
  • I don't know how exactly automapper works (reflection?) but I'd just serialize `B` and then deserialize it as `A`. Obviously serialized data shouldn't contain type info or you have to somehow override it (in case of `TypeNameHandling.Auto` json it would be custom `JsonBinder`). – Sinatr Mar 06 '17 at 11:14

4 Answers4

5

You can always implement an implicit or explicit cast operator:

public class B
{
     public static explicit operator A(B b)
     {
          return new A() {
                           p1 = b_obj.p1,
                           p3 = b_obj.p3,
                         }
     }

     //...
 }

And now, you can simply write any time you need an A from a B:

var a = (A)b;

If you don't have access to either A or B then you could implement an extension method:

public static A ToA(this B b)
{
    return ...
}

And the use would be similar:

var a = b.ToA();
InBetween
  • 32,319
  • 3
  • 50
  • 90
2

You can use AutoMapper (see denisv's answer) which provides mappings between classes based on name. You can then customize your mappings if you want to.

You can also write some extension methods:

public static class Extensions
{
    public A ToA(this B b)
    {
        return new A() 
        {
            p1 = b_obj.p1,
            p3 = b_obj.p3,
        };
    }
}
fharreau
  • 2,105
  • 1
  • 23
  • 46
1

You can use automapper http://automapper.org/ Then you can use it like this:

AutoMapper.Mapper.CreateMap<A, B>();
var a = ...
var model = AutoMapper.Mapper.Map<B>(a);
denisv
  • 319
  • 3
  • 11
  • I think it is a better solution than Murad Garibzada's, because of the performance. You can then use this solution within cast operator/extension methods (see @InBetween answer which is more complete than mine) to shorten your code base. – fharreau Mar 06 '17 at 10:14
  • I don't like it. It is not refactoring safe. If I refactor __B.p1__ to __B.q1__ the property names do not line up and I may get an obscure runtime failure or data corruption rather than a compile time failure. To be sure you don't get errors through refactoring then you have to write a unit test using https://github.com/AutoMapper/AutoMapper/wiki/Configuration-validation – bradgonesurfing Mar 06 '17 at 10:40
  • @bradgonesurfing I provided basic syntax. If you want compiler help, you can use extended syntax for mapping rules: http://stackoverflow.com/questions/6985000/how-to-use-automapper-formember – denisv Mar 06 '17 at 10:53
0

First of all initialize B class and set values. Then create such a class:

public static void CopyPropertyValues(object source, object  destination)
{
var destProperties = destination.GetType().GetProperties();

foreach (var sourceProperty in source.GetType().GetProperties())
{
    foreach (var destProperty in destProperties)
    {
        if (destProperty.Name == sourceProperty.Name && 
    destProperty.PropertyType.IsAssignableFrom(sourceProperty.PropertyType))
        {
            destProperty.SetValue(destination, sourceProperty.GetValue(
                source, new object[] { }), new object[] { });

            break;
        }
    }
}

}

and pass A and B class to this class as Parameter

Murad
  • 523
  • 4
  • 17
  • While this answer is a good answer, you have to know that this uses reflexion and has an impact on the performance. – fharreau Mar 06 '17 at 10:10
  • But it is best way, and you don't care about which fields exist in classes, it is enough to know both classes properties are same. – Murad Mar 06 '17 at 10:12
  • As I said, it is a good answer. Is just warned the OP about the performance impact. I am not the one who downvotes your post. – fharreau Mar 06 '17 at 10:16