2

Let's say I have 3 classes.

public Class1{
public string field1{get;set;}
}

public Class2:Class1 {
public string field2{get;set;} 
}

public Class3:Class2 {
public string field3{get;set;} 
}


Class3 obj3 = new Class3();
Class2 obj2 = obj3;

Class1 obj1 = obj2;

public class MyInfoService : ServiceBase<MyReuest>
{
      protected override object Run(MyReuest request)
        {
           Class3 obj3= FindObjClass3("someid");
           Class2 obj2 = DoSomethingObj3Class3(obj3);
           Class1 obj1= obj2; // service users have to get only Class1 fields 
           return obj1;

        }
}

The problem starts when I want to return obj1 as response with format=json , the output json contains properties from obj2 and obj3.

I just want that obj1 is serialized as response only with its properties.

Is there a way to do this ?

Erhan A
  • 691
  • 11
  • 21
  • can you show your code you tried so far? – L.B Aug 19 '12 at 15:42
  • My code is implemented as same as the pseudo code in my question. – Erhan A Aug 19 '12 at 15:44
  • But I can't see any code related to serialization. – L.B Aug 19 '12 at 15:47
  • ohhh , Servicestack does serialization itself if the request contains format parameter.If format=json , the response is serialized to json and if format=xml the response is serialized to xml. – Erhan A Aug 19 '12 at 15:49
  • I think the best way to extend serialization layer. If you use Newtonsoft.Json define custom IContractResolver by inheritance from DefaultContractResolver and override GetSerializableMembers method in order to ignore excess members. – Pavel Bakshy Aug 19 '12 at 15:56
  • 1
    ServiceStack uses its own serializer. https://github.com/ServiceStack/ServiceStack.Text – Erhan A Aug 19 '12 at 16:15

2 Answers2

2

Don't try and abuse inheritance, they're bad practice for DTOs: Getting ServiceStack to retain type information

It's also a bad idea to use inheritance to DRY properties - these unnecessary abstractions should be avoided. Automatic properties are a terse way to express the structural fields of your type. Use interfaces instead, when you need them: http://ayende.com/blog/4769/code-review-guidelines-avoid-inheritance-for-properties

Community
  • 1
  • 1
mythz
  • 141,670
  • 29
  • 246
  • 390
  • Result is the same by interface implemantation or I could not make it work but nothing changed.Class1 is the superclass of all why should i have another insatance of the same class just to avoid inheritance. PS : obj1.ToJson() creates correct json by ServiceStack.Text. Regarding your explanations , I was expecting Class2,Class3 properties in the .ToJson() created result, but there is not and this is correct. – Erhan A Aug 19 '12 at 17:23
  • 1
    The solution is not to try and abuse inheritance. You will have a much cleaner, more intuitive code-base if you use **clean DTOs** and auto-mappers for copying data between your models. Interfaces allow you to treat handle different DTOs with same fields generically. – mythz Aug 19 '12 at 17:32
  • Ok , I clearly understand your way.But I wonder why obj1.ToJson() shows me the correct json and why returning obj1 in overrided Run method does not create correct json as response ? – Erhan A Aug 19 '12 at 17:40
  • See 1st link in answer: i.e. base class needs to be abstract. – mythz Aug 19 '12 at 17:42
  • I don't know what the trick is but abstract or interface implemantation did not change anything on the response serialization.It will be very helpful if you can share an example code suits my psuedo code? – Erhan A Aug 19 '12 at 20:11
1

If you can't touch serialization level, the try to Clone object before return.

public class Class1 : ICloneable {
    public string Prop1 { get; set; }

    public object Clone() {
        return new Class1 { Prop1 = Prop1 };
    }
}

public class Class2 : Class1 {
    public string Prop2 { get; set; }

    public new object Clone() {
        return new Class2 { Prop1 = Prop1, Prop2 = Prop2 };
    }
}

Then use use:

public class MyInfoService : ServiceBase<MyReuest>
{
    protected override object Run(MyReuest request)
    {
       Class3 obj3 = FindObjClass3("someid");
       Class2 obj2 = DoSomethingObj3Class3(obj3); 
       return ((Class1) obj2).Clone();
    }
}

NOTE: For different implementations of Clone method depending on type use new keyword instead of override

Pavel Bakshy
  • 7,697
  • 3
  • 37
  • 22
  • Thanks for the answer but i need something on ServiceStack layer.I don't want to create more objects by cloning or by implicit casting just to avoid more memory usage though I have caching mecanism on ServiceStack.The service will be called more than 10.000.000 times in a day. – Erhan A Aug 19 '12 at 16:31
  • +1 for an alternate solution which works.But in some conditions need so much coding. – Erhan A Aug 28 '12 at 12:48