0

Is there a way to convert a nested object to an object. For example lets say I have an object of class ABC as shown below.

class ABC
{
   int id {get;set;}
   
   XYZ myobj {get;set}
}

class XYZ
{
  string name {get;set;}
  string addr {get;set;}
}

Is there any way to convert this ABC class object to UVW class object like below.

class UVW
{
  int id {get;set;}
  string name {get;set;}
  string addr {get;set;}
 }

6
  • Just assign UVW.id = abc.id ? Commented Mar 5, 2021 at 4:56
  • @MichaelMao This is just an example. my actual class has too many fields and api returns thousands of records. I don't want to convert object manually in a loop by assigning each property. I am looking for a generic way which can be applied to any class because I need to do similar activity for multiple classes in the application. Commented Mar 5, 2021 at 5:06
  • Amount of records doesn't matter. Amount of field will not matter much as well, because you need to "type" them only once and reuse them. Commented Mar 5, 2021 at 5:09
  • There are no such magic which will do that. Event with reflection you will need to loop through properties and map them one to another. One can suggest you to use Automapper library, but you will end up with same amount of code to create a map then just do it manually once. Commented Mar 5, 2021 at 5:11
  • Is the API response actually a JSON? In that case, you probably want a custom JsonConverter, to deserialize to a specific class model directly. Commented Mar 5, 2021 at 5:22

2 Answers 2

1

If you are looking for a provision in C# to convert an object of ABC to an object of UVW, then am afraid there is no such thing.

If you want, you could just write your own conversion logic though (after making the properties public):

private UVW ConvertToUVW(ABC abc)
{
    if (abc == null)
    {
        return null;
    }

    var uvw = new UVW();
    uvw.id = abc.id;
    uvw.name = abc.myobj?.name;
    uvw.addr= abc.myobj?.addr;

    return uvw;
}
Sign up to request clarification or add additional context in comments.

1 Comment

OP says in a comment their "actual class has too many fields and [... are] looking for a generic way which can be applied to any class".
1

You can use Automapper's automatic flattening for this. It works by naming convention, to map a Foo.Bar in the source to a FooBar destination, or by configuration where the first configured match wins in case of conflicts.

Given these source types:

class SourceRoot
{
    public int Id { get; set; }

    public Foo Foo { get; set; }
    public Bar Bar { get; set; }
}

class Foo
{
    public string Name { get; set; }
    public string Addr { get; set; }
}

class Bar
{
    public string Name { get; set; }
    public string Addr { get; set; }
}

Which is to be mapped to this target:

class TargetFlattened
{
    public int Id { get; set; }
    public string Name { get; set; }
    public string Addr { get; set; }
    public string BarAddr { get; set; }
}

You can automap from source to flattened target like this:

var source = new SourceRoot
{
    Id = 42,
    Foo = new Foo
    {
        Addr = "FooAddr",
        Name = "FooName"
    },
    Bar = new Bar
    {
        Addr = "BarAddr",
        Name = "BarName"
    }
};

var configuration = new MapperConfiguration(cfg => {
            
    // First, map complex property types
    cfg.CreateMap<Foo, TargetFlattened>();
    cfg.CreateMap<Bar, TargetFlattened>();

    // Then the root type
    cfg.CreateMap<SourceRoot, TargetFlattened>()
        .IncludeMembers(a => a.Foo, a => a.Bar)
        .ReverseMap();
});
var target = configuration.CreateMapper().Map<TargetFlattened>(source);

Note that this will yield:

Id: 42
Addr: FooAddr
BarAddr: BarAddr
Name: FooName

The IncludeMembers() configuration will map members that don't adhere to the naming convention (Name instead of FooName for Foo.Name).

Meaning, if you have multiple complex properties with a Name property, you'll get the first included member's Name property mapped into your target's Name.

If you swap them to .IncludeMembers(a => a.Bar, a => a.Foo), your Name will be "BarName".

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.