How to rename an inherited API member in a subclass? - c#

Say I have:
public class Parent{
[ApiMember(Name = "parentItem")]
public string Item {get; set;}
}
and
public class Child : Parent {
[ApiMember(Name = "childItem")]
public new string Item {get; set;}
}
Since the 'Item' property in the parent class should be hidden, why does making a request with {"childItem": "something"} returns Could not find property childItem on RequestObject? That said, what is the best way (or is there a way) to rename inherited API members/properties in the subclass?

[DataContract] and [DataMember] attributes affect serialization where as [Api*] attributes are only used to document and add extra metadata about your API, but it doesn't affect serialization behavior.
So you should instead change your DTOs to:
[DataContract]
public class Parent
{
[DataMember(Name = "parentItem")]
public virtual string Item { get; set; }
}
[DataContract]
public class Child : Parent
{
[DataMember(Name = "childItem")]
public override string Item { get; set; }
}
Where they will be used when serializing in most of ServiceStack's serializers, e.g:
var json1 = new Parent { Item = "parent" }.ToJson();
json1.Print();
var json2 = new Child { Item = "child" }.ToJson();
json2.Print();
Which outputs:
{"parentItem":"parent"}
{"childItem":"child"}
You can try this example Live on Gistlyn.

Try making the property virtual in the parent and then simply override it (without new keyword) in the child class like that:
public class Parent{
[ApiMember(Name = "parentItem")]
public virtual string Item {get; set;}
}
public class Child : Parent {
[ApiMember(Name = "childItem")]
public override string Item {get; set;}
}

Related

serialize derived class member using XmlChoiceIdentifierAttribute

I have WSDL service class in which I would like to add extra properties. When I am trying to deserialize my derived class its giving error "You need to add XmlChoiceIdentifierAttribute to the 'ObjCreatePaperClipTransaction' member."
Here is the code I wrote on top of service classes. (executeCreatePaperClipTransaction & CreatePaperClipTransactionType are classes from proxy object)
namespace MyProject.DTO
{
[XmlType("executeCreatePaperClipTransaction")]
public partial class CustomExecuteCreatePaperClipTransaction : executeCreatePaperClipTransaction
{
[XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
[XmlElement("CreatePaperClipTransaction")]
public CustomCreatePaperClipTransactionType ObjCreatePaperClipTransaction { get; set; }
}
public partial class CustomCreatePaperClipTransactionType : CreatePaperClipTransactionType
{
[XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public executeCreateLoanIncrease ObjLoanIncreaseRequest { get; set; }
[XmlElement(Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 1)]
public executeCreateFreeFormEventFeePayment ObjFreeFormEventFeePaymentRequest { get; set; }
}
}
When I remove [XmlElement("CreatePaperClipTransaction")] line, its working fine. But in the seralized xml i want tag name to be CreatePaperClipTransaction and not ObjCreatePaperClipTransaction
I went through this answer but I am not sure how can i implement in my case https://stackoverflow.com/a/20379038/1169180
Rather than adding two separate [XmlElement] attributes to your ObjCreatePaperClipTransaction property, you should add one single attribute with all necessary information:
[XmlType("executeCreatePaperClipTransaction")]
public partial class CustomExecuteCreatePaperClipTransaction : executeCreatePaperClipTransaction
{
[XmlElement(ElementName = "CreatePaperClipTransaction", Form = System.Xml.Schema.XmlSchemaForm.Unqualified, Order = 0)]
public CustomCreatePaperClipTransactionType ObjCreatePaperClipTransaction { get; set; }
}
Working .Net fiddle.
When you add multiple [XmlElement] attributes to a property, you are informing XmlSerializer that multiple different XML element names should be bound to the same property, for instance because the property value is polymorphic:
public class BaseClass
{
}
public class DerivedClass : BaseClass
{
}
public class RootObject
{
[XmlElement(ElementName = "BaseClassProperty", Type = typeof(BaseClass))]
[XmlElement(ElementName = "DerivedClassProperty", Type = typeof(DerivedClass))]
public BaseClass Property { get; set; }
}
In the example above, if the Property is assigned a DerivedClass value, the following XML will be generated:
<RootObject>
<DerivedClassProperty />
</RootObject>
That doesn't seem to apply here. You just want to bind your property to the XML element name <CreatePaperClipTransaction>.

Nest XML Elements - XML Serialization

I need to sandwich an element inside of another element. Is it possible to serialize XML like this?
http://pastebin.com/7qDE7Ses
Here is my class
[XmlRoot(ElementName = "SalesOrderMod")]
public partial class SalesOrderMod
{
[XmlElementAttribute(Order = 1)]
public string TxnID { get; set; }
[XmlElementAttribute(Order = 2)]
public string EditSequence { get; set; }
[XmlElementAttribute(Order = 3)]
public string ShipDate { get; set; }
[XmlElementAttribute(Order = 4)]
public ListRef ShipMethodRef = new ListRef();
public bool ShouldSerializeShipMethodRef()
{
return !(String.IsNullOrEmpty(ShipMethodRef.FullName));
}
[XmlElementAttribute(Order = 5)]
public string Other { get; set; }
[XmlElementAttribute(Order = 6, ElementName = "SalesOrderLineMod")]
public List<LineMod> SalesOrderLineMod = new List<LineMod>();
[XmlElementAttribute(Order = 7, ElementName = "SalesOrderLineGroupMod")]
public List<LineMod> SalesOrderLineGroupMod = new List<LineMod>();
}
You originally indicated you would like to serialize a series of elements inside an XML document like so:
<SalesOrderLineRet>
</SalesOrderLineRet>
<SalesOrderLineGroupRet>
</SalesOrderLineGroupRet>
<SalesOrderLineRet>
</SalesOrderLineRet>
You can if the types that correspond to SalesOrderLineRet and SalesOrderLineGroupRet have some common base type T, and they are stored in a List<T>. For instance, the following class definitions:
public abstract class SalesOrderLineRetBase
{
}
public class SalesOrderLineRet : SalesOrderLineRetBase
{
}
public class SalesOrderLineGroupRet : SalesOrderLineRetBase
{
}
public class RootObject
{
[XmlElement(typeof(SalesOrderLineRetBase))]
[XmlElement(typeof(SalesOrderLineRet))]
[XmlElement(typeof(SalesOrderLineGroupRet))]
public List<SalesOrderLineRetBase> SalesOrders { get; set; }
}
Will, when serialized, produce the following XML:
<RootObject>
<SalesOrderLineRet />
<SalesOrderLineGroupRet />
</RootObject>
Using [XmlElement(typeof(T))] tells XmlSerializer that the list should be serialized without an outer container element, and that items of type T can be expected to be found in the list. You must apply [XmlElement(typeof(T))] once for each type T that will be stored in the list.
(You can use List<object> if the types in the list have no other more derived base type, however I don't recommend that. I would instead recommending grouping the possible types of list entry under a specific base type.)
If you would prefer your list to be serialized with an outer container element, you can use [XmlArray] and [XmlArrayItem(typeof(T))]:
public abstract class SalesOrderLineRetBase
{
}
public class SalesOrderLineRet : SalesOrderLineRetBase
{
}
public class SalesOrderLineGroupRet : SalesOrderLineRetBase
{
}
public class RootObject
{
[XmlArray("SalesOrders")]
[XmlArrayItem(typeof(SalesOrderLineRetBase))]
[XmlArrayItem(typeof(SalesOrderLineRet))]
[XmlArrayItem(typeof(SalesOrderLineGroupRet))]
public List<SalesOrderLineRetBase> SalesOrders { get; set; }
}
Which produces the following XML:
<RootObject>
<SalesOrders>
<SalesOrderLineRet />
<SalesOrderLineGroupRet />
</SalesOrders>
</RootObject>
You must apply [XmlArrayItem(typeof(T))] for each type T that will be stored in the list.
(Since you don't include the relevant classes and XML in your question, I'm not sure which one you might want.)

Inheritance, how to inherit parent class without grandparent

I am using ASP.Net Web API 2 and want to create some complex input parameter classes.
I have classes in my library as
public class GrandParent
{
public int Id {get;set;}
public string GrandParentName {get;set;}
}
public class Parent : GrandParent
{
public string ParentName {get;set;}
}
Now I only need Parent class properties in my child class and I am doing so
public class Child : Parent
{
public string ChildName {get;set;}
}
When I create object of Child class, I want only two properties, which are
Child objChild = new Child();
objChild.ParentName;
objChild.ChildName;
I don't want GrandParentName property with objChild. Is there any way to skip grand parent classes in inheritance structure as I want to pass this class as API action parameter.
I am feeling lack of multiple inheritance in C# here.
I may be misunderstanding something but I think you are going too far with inheritance. You might look to the composite pattern.
I think you are confused between the role of each object compared to each others and inheritance. I am not sure you need all these classes. Here is what I would do :
interface IPerson
{
public int Id { get; set; }
public string Name { get; set; }
public string ParentName { get; }
}
class Person : IPerson
{
public int Id { get; set; }
public string Name { get; set; }
protected IPerson Parent { get; set; }
public string ParentName { get { return this.Parent != null ? this.Parent.Name : String.empty; } }
public Person(IPerson parent = null)
{
this.Parent = parent;
}
}
And once you have this, you can achieved what you want :
var grandParent = new Person();
var parent = new Person(grandParent);
var child = new Person(parent);
I hope I didn't miss any crucial point :D.
As it seems, you may need to change your GrandParent from class to interface, then that might work, if you need those properties just make extra class that implements interface. Remember that you can implement as many interfaces as you need on a single class. And still they have common name for use in Lists and stuff.
fharreau gave example.
If you want better example you should make some data diagram concerning data in question.

What is the best way to populate base properties?

I'm wondering if someone can help me with what is the best way to populate the base properties of a derived class. I would like to use one method to populate the properties of the base whether the base or the child is being used.
Here is an example of what I am asking:
public class Parent
{
public string Id {get; set;}
}
public class Child : Parent
{
public string Name {get; set;}
}
public Parent GetParent(int ID)
{
Parent myParent = new Parent();
//Lookup and populate
return Parent;
}
public Child GetChild(string name)
{
Child myChild = new Child();
//Use the GetParent method to populate base items
//and then
//Lookup and populate Child properties
return myChild;
}
I think you might be overcomplicating things a bit. Take a look at this code that uses inheritance and constructors to initialize objects:
public class Parent
{
public string Id {get; set;}
public Parent(string id)
{
Id = id;
}
}
public class Child : Parent
{
public string Name {get; set;}
public Child(string id, string name) : base(id) // <-- call base constructor
{
Name = name;
}
}
It uses constructors for initialization and the base keyword to call the parent constructor from the derived class. I would go this direction unless you really need to have a factory method construct your object.
Something like this if you don't want to do it in constructor.
Note: the constructor is not always called, especially if the type is desirialized using certain serializators.
public class Parent
{
public string Id {get; set;}
public virtual void InitPorperties() {
//init properties of base
}
}
public class Child : Base {
public override void InitProperties() {
//init Child properties
base.InitProperties();
}
}
After this you can use it like:
public Parent GetParent(int ID)
{
var myParent = new Parent();
parent.InitProperties();
return myParent;
}
public Parent GetChild(int ID)
{
var child= new Child();
child.InitProperties();
return child;
}
As anything it has other side of coin: the caller has to call InitProperties method in oder to get correctly initialized object.
If the serialization/desialization is not a concern in your case, stick with constructors, in practice call this methods inside ctors of every type (Parent, Child)
If you dont want to use a standard way to just
Child myChild = new Child();
myChild.Name = "name";
myChild.Id = "1";
You can populate them via the constructor like this.
public class Parent
{
public Parent(string id)
{
Id = id;
}
public string Id { get; set; }
}
public class Child : Parent
{
public Child(string id, string name)
: base(id)
{
name = Name;
}
public string Name { get; set; }
}
And when you isntanciate it
Child myChild = new Child("1", "name");
Which in my opinion is a quite neat way to do it.

Acessing object like by Index, but by name in C#

I have to classes, Father and Child (by example)
A snippet of my implementation
Class Father.cs
public class Father
{
public int Id { get; set; }
public string Name { get; set; }
public List<Child> Children { get; set; }
public Father()
{
}
}
Class Child.cs
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public Child()
{
}
}
I'am trying to do something like this
Father f = new Father();
f.Children[0]; // ok
f.Children[1]; // ok
f.Children["John"]; // Duh!
I now, its wrong, i need to implement something in Child Class, i tryed this
public Child this[string name]
{
get
{
return this;
}
}
But this doesnt work.
How can i implement this feature for my class Child?
A List<T> doesn't have a string indexer; you could add one to the Father class, but the usage will be:
var child = parent["Fred"];
(no .Children)
For the indexer itself: Try (in the indexer):
return Children.FirstOrDefault(c=>c.Name==name);
To get an indexer on the list itself, you would have to create a custom list type and add the indexer there.
IMO, a method may be clearer (on Father):
public Child GetChildByName(string name) {...}
Or you can set it up like this:
public class Father
{
public int Id { get; set; }
public string Name { get; set; }
public Children Children { get; set; }
public Father()
{
}
}
public class Children : List<Child>
{
public Child this[string name]
{
get
{
return this.FirstOrDefault(tTemp => tTemp.Name == name);
}
}
}
public class Child
{
public int Id { get; set; }
public string Name { get; set; }
public Child()
{
}
}
Then you call it how you want.
In father class, you could write following code:
public Child this[string name]
{
get
{
return Children.Where(c => c.Name == name);
}
}
and use it like:
Father f = new Father();
f.Children[0]; // ok
f.Children[1]; // ok
f["John"]; // ok!
You are treating the List of Children like a Dictionary (Dictionaries can be accessed by key). Just change your List to a Dictionary and set the string to be the Child's name.
You could make the Children List into an OrderedDictionary so that you can reference it by index or key and then add the objects with the name as the key. Just so you know though, any of these options can run into issues if you have multiple children with the same name.

Categories

Resources