Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Auto generating DataContract classes from Business Object Classes

I'm currently creating a .NET C# API. I have many classes, and some of them have to be transferred through a REST service as JSON. For example, I may have an account object with a lot of business meta-data:

public class Account
{
    public ComplicatedClass SomeProperty { get; set; }
    public string SomeOtherProperty { get; set; }
}

There are many classes, and many more that are nested (as demonstrated by ComplicatedClass type property). To avoid inundating this business-object with [DataMember] etc. Attributes that will make this class a mess, I want to make a DTO for JSON:

public class AccountDTOForJSON
{
    [DataMember(Name="someProperty")]
    public ComplicatedClassDTOForJson SomeProperty { get; set; }

    [DataMember(Name="someOtherProperty")]
    public string SomeOtherProperty { get; set; }
}

My problem is, there doesn't seem to be any tools (that I can find) to auto-generate these DataContract classes, and also provide code for mapping properties back/forth.

I can, of course, do all this work manually (worst case), or roll my own tool to generate/map (second worse case). But, I'd like to know first if there's already a tool to do this kind of thing that I can use to save myself time.

like image 387
automaton Avatar asked Feb 01 '13 18:02

automaton


3 Answers

This is a good question. I'm actually going to be doing something similar to it in a project I am working on.

I would suggest that there are really two problems here: the first is to generate DTO code from your business objects, and the second is to do the mapping between business object and DTO.

I could not find a code generator for this purpose after spending about a half hour on Google. Perhaps I'm not searching for the right thing, or possibly there isn't one out there (so if someone knows of one, please chime in). The only tool I found that looks promising is NHydrate (http://www.codeproject.com/Articles/42885/NHydrate-Code-Generator), but I did not actually download it or test it.

A mapping tool that I've used in the past is AutoMapper (https://github.com/AutoMapper/AutoMapper/wiki/Getting-started) - it will attempt to figure out the relationship between your business objects and DTOs, and will be able to do two-way mapping.

like image 167
theMayer Avatar answered Nov 18 '22 08:11

theMayer


I've done this before by:

  1. Use the XSD tool to generate schemas from your compiled DTO assembly.
  2. Use svcutil to generate DataContracts from the .xsd generated in step 1.


Edit:

The above assumes that your Account class is a DTO (since the only indication that you gave in your example was that it contains two properties so I assume that it is merely used to transfer state and not define behavior). If that is the case, and you simply want the DataContract version of the Account class then the above should work. You still have to provide the code to map the Account class to the serializable Account class (generated by svcutil).

like image 1
jeuton Avatar answered Nov 18 '22 10:11

jeuton


On way is to modify your code generation engine (.tt file in my case or the T4 file) and add the DataMember attribute to the properties you want. To add it to an auto generated POCO class, look for the <#=codeStringGenerator.Property(edmProperty)#> and add the [DataMember] right above it:

    var simpleProperties = typeMapper.GetSimpleProperties(entity);
    if (simpleProperties.Any())
    {
        foreach (var edmProperty in simpleProperties)
        {
#>
    [DataMember]
    <#=codeStringGenerator.Property(edmProperty)#>
<#
        }
    }

Some part of the code above should already be in the T4 file. you might need to find it and modify it by adding [DataMember] to it.

Also, you can create your DTO file in an arbitrary location with desired attributes. For example the code below is creating an interface for all the entities in a folder named Interface and also name the interface like I{EntityName}Repository.cs. You can generate DTOs in the same way.

foreach (var entity in typeMapper.GetItemsToGenerate<EntityType>(itemCollection))
{
    var host = this.Host.ResolvePath("App.config");
    var savepath = host.Replace("App.config","")+"Interface\\" + "I"+entity.Name+"Repository" +".cs";
    var readpath = host.Replace("App.config","") + "Templates\\";

    if (!File.Exists(savepath))
    {
        using (StreamReader sr = new StreamReader(readpath+"RepositoryInterfaceTemplate.txt"))
     {
                String line = sr.ReadToEnd();
               line = line.Replace("{RepositoryInterface}","I"+entity.Name+"Repository");
                line =line.Replace("{EntityName}",entity.Name);


        using (StreamWriter sw = File.CreateText(savepath))
        {       
            sw.WriteLine(@line);        
        }
      }
    }
}
like image 1
Amir Shirazi Avatar answered Nov 18 '22 09:11

Amir Shirazi