Consider the following class:
[Serializable]
public class MyClass
{
[XmlAttribute("id")]
public int ID { get; set; }
[XmlArrayItem("User")]
public List<string> Users { get; set; }
[XmlArrayItem("Role")]
public List<string> Roles { get; set; }
}
Now I want to transform the class definition to get following expected result of XML serialization for an instance of the class:
<MyClass id="123">
<Access>
<User>User A</User>
<User>User B</User>
<User>User C</User>
<Role>Role A</Role>
<Role>Role B</Role>
<Role>Role C</Role>
</Access>
</MyClass>
Moreover it must be deserializable. I tried to apply [Xml Array("Access")] attribute to both Users and Roles properties, but an InvalidOperationException occurs.
It would be great if the question can be solved without IXmlSerializable implementation.
It looks like you just need to make an "Access" class to nest your Users/Roles.
[XmlRoot(ElementName="Access")]
public class Access {
[XmlElement(ElementName="User")]
public List<string> User { get; set; }
[XmlElement(ElementName="Role")]
public List<string> Role { get; set; }
}
[XmlRoot(ElementName="MyClass")]
public class MyClass {
[XmlElement(ElementName="Access")]
public Access Access { get; set; }
[XmlAttribute(AttributeName="id")]
public string Id { get; set; }
}
Related
Im working on ASMX service that allows me to work with databases and their tables. The schema looks like this
[DataContract]
public class DataBase
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Table> Tables { get; set; }
...
}
[DataContract]
public class Table
{
[DataMember]
public string Name { get; set; }
[DataMember]
public List<Column> Columns { get; set; }
[DataMember]
public List<List<object>> Data { get; set; }
...
}
[DataContract]
public class Column
{
[DataMember]
public string Name { get; set; }
[ DataMember]
public string Type { get; set; }
...
}
"Data" field is meant to keep a table of all values of different types. The problem is - i have to work with a few of custom types:
public class Email
{
[DataMember]
public string address { get; set; }
...
}
public class Strings : List<string>
{
public Strings(IEnumerable<string> collection) : base(collection) { }
...
}
And the problem is that web service does not create references to these types. I do not use them in methods explicitly, but store in table. Using KnownType and DataContract did not help me, and when i created same classes in a client app, i have exceptions. Please, help?
I fixed it: basically i created dummy methods that returned object of nedded types, deleted the method references from client app and it worked.
XML to be deserialized:
<?xml version="1.0" encoding="UTF-8" standalone="yes" ?>
<changes next="296">
<change>
<objectid>E702C43C-E04B-450B-BEBC-76646AB299C5</objectid>
<parentid>ED98C97F-A202-48ED-AEEA-34362508A30B</parentid>
<objecttype>file</objecttype>
<listentype>remove</listentype>
</change>
<change>
<objectid>3A242975-CEF0-432B-A997-B33D85C138C8</objectid>
<parentid>ED98C97F-A202-48ED-AEEA-34362508A30B</parentid>
<objecttype>file</objecttype>
<listentype>add</listentype>
</change>
</changes>
Data models used:
[XmlRoot("changes")]
public class ChangeListener
{
public List<Change> Changes { get; set; }
}
[XmlRoot("change")]
public class Change
{
[XmlElement("objectid")]
public Guid objectid { get; set; }
[XmlElement("parentid")]
public Guid parentid { get; set; }
[XmlElement("objecttype")]
public string objecttype { get; set; }
[XmlElement("listentype")]
public string listentype { get; set; }
}
Deserialization code, here result is above xml in string format:
(ChangeListener)new XmlSerializer(typeof(ChangeListener)).Deserialize(new MemoryStream(Encoding.UTF8.GetBytes(result)))
But I am getting errors for this code; I also tried couple of things e.g. marked Changes property of ChangeListener class with [XmlElement("changes")] instead of marking class as xmlroot but it also did not worked.
Kindly suggest good approach for this issues.
The problem is that the Changes List in the ChangeListener is confusing the serializer because there's nothing called 'Changes' in the XML.
The only change we need to make is to annotate the declaration of Changes with [XmlElement("change")] as below:
[XmlRoot("changes")]
public class ChangeListener
{
[XmlElement("change")]
public List<Change> Changes { get; set; }
}
The XML shown then deserializes correctly.
The Class for mentioned XML should look like below.
[XmlRoot(ElementName="change")]
public class Change {
[XmlElement(ElementName="objectid")]
public string Objectid { get; set; }
[XmlElement(ElementName="parentid")]
public string Parentid { get; set; }
[XmlElement(ElementName="objecttype")]
public string Objecttype { get; set; }
[XmlElement(ElementName="listentype")]
public string Listentype { get; set; }
}
[XmlRoot(ElementName="changes")]
public class Changes {
[XmlElement(ElementName="change")]
public List<Change> Change { get; set; }
[XmlAttribute(AttributeName="next")]
public string Next { get; set; }
}
Try changing the type of objectid and parentid from Guid to string.
Share the error details if you still get errors.
I have a base class like this-ish:
public class Baseclass
{
public string Id { get; set; }
public string Type { get; set; }
public string Name { get; set; }
}
...and many classes that inherit these properties, like this-ish:
public class Thing: Baseclass
{
public string Size{ get; set; }
public string Color{ get; set; }
public string Smell{ get; set; }
}
Now, I don't want to serialize all of these properties (mvc/jsonresult), so I use [JsonIgnore] on the properties of a class I want to exclude, and that works fine. The problem is that I don't want to serialize all the inherited properties for a class either. I've asked around and gotten the following answer:
Ex: I don't want to serialize the inherited Id from Baseclass in Thing.
I should make Id in Baseclass virutal:
public virtual string Id { get; set; }
and add the following to the Thing class:
[JsonIgnore]
public override string Id { get; set; }
...but this doesn't work, I'm afraid. I can get around it rebuilding the class hierarchy. but I would prefer a simpler solution. Any suggestions as to why this solution didn't work or alternatives to exclude certain inherited properties?
My program is starting to get pretty big. and i have found that its starting to do the same thing in multiple area's.
Im trying to figure out how i can make it more efficient.
So i have an object that looks like this
public class TreeViewNode
{
public TreeViewNode()
{
Children = new ObservableCollection<TreeViewNode>();
}
public String Name { get; set; }
public string Description { get; set; }
public ObservableCollection<TreeViewNode> Children { get; set; }
}
i also have another object that looks like this;
public class ComputerObject
{
public String Name { get; set; }
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
public ObservableCollection<Object> Children { get; set; }
}
Both these items need to have some of the same properties..
at the moment they both have the Children Property and the Name Property. but they both need to have some other common properties added to them.
so i have tried something like this.
public class BaseObject
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
public BaseObject()
{
Children = new ObservableCollection<object>();
}
}
public class ComputerObject: BaseObject
{
public Int32 UUID { get; set; }
public DateTime Created { get; set; }
}
public class TreeViewNode: BaseObject
{
public String IconPath { get; set; }
}
Now this is just a cut down version of what i am implementing, i have alot of objects that share the same properties. and some that dont and mix and match. and i cannot figure out the best implimentation for this.
My Objects are becoming very cluttered, and when i rename a property i find that i have to rename it in several area's and this isnt the way its ment to be.
can someone please advise how i would implement multiple objects that share the same property names?
In my opinion you should not let classes inherit from one baseclass when these childclasses are not related to each other (like #Sriram Sakthivel asked Animal < Dog,Cat) just to share the same properties.
You should determine which classes are related (cat, dog are animals; car, motorcycle are vehicles) and then create baseclasses based on these "groupings".
I would look into decorator pattern. In short, you dont share common properties via inheritance. You make classes that contain common properties, and use these classes as properties in your end classes.
EDIT: Example is actually just a standard composition, it should work nevertheless
E.G.
public class Decorator1
{
public String Name { get; set; }
public ObservableCollection<Object> Children { get; set; }
public string Description { get; set; }
}
public class Decorator2
{
public long Id { get; set; }
}
public class ClassA
{
public Decorator1 TreeNodeImpl;
}
public class ClassB
{
public Decorator1 TreeNodeImpl;
public Decorator2 LongIdImpl;
}
I have a class below, i have extracted all the properties to a Interface but i don't seem to be able to extract it... Obviously create a new object like
ITestItem item = new TestItem();
doesn't give me access to Properties which is an instance of Meta class.
I also wanted to stop anyone from create an instance of Meta class outside of TestItem... i tried marking it as internal but that would allow me because Properties is public.
Also i am unsure whether i need to have an interface for META??
here is my class... can anyone help?
public class TestItem : ITestItem
{
public bool Enabled { get; set; }
public Meta Properties = new Meta();
public List<int> Items { get; set; }
public class Meta
{
internal Meta
{
}
public string Name { get; set; }
}
public TestItem()
{
this.Items = new List<int>();
}
}
EDIT
I have uppdated the class above to include an internal constructor for Meta so it can't be instanciated outside the class.
Here is my interface i have (as suggested by giddy)... It says now that it doesn't implement Properties
public interface ITestItem
{
bool Enabled { get; set; }
Meta Properties { get; set; };
List<int> Items { get; set; }
}
So you would:
Not want to maybe use the term extract to interface, maybe your idea about interfaces is a little wrong. You want to do some reading here.
Define the Meta class inside the Test class. Mark the constructor internal or private depending on where you want to create an instance.
Make a property that exposes the Meta class outside of the Test class
public class TestItem : ITestItem
{
public TestItem()
{
this.Properties = new Meta();//set it from here
this.Items = new List<int>();
}
public bool Enabled { get; set; }
//make it private set if you don't want an outsider setting it
public Meta Properties {get;private set}
public List<int> Items { get; set; }
public class Meta
{//make it private if you only create an instance here.
internal Meta(){}
public string Name { get; set; }
}
}
You also add the Meta property to your interface:
public interface ITestItem
{
bool Enabled { get;set;}
Meta Properties { get;set;}
List<int> Items { get;set;}
void ScheduleItem();
}
You may try this one. Its compiled in VS2010. It is better anyway to extract an interface for Meta also for the sake of "decoupling classes" to allow unit testing. Please search and read about - "decoupling classes".
public class Meta { // Do not make this class a child class for flexibility and testing purposes.
public string Name { get; set; }
}
public class IMeta {
string Name { get; set; }
}
public class TestItem : ITestItem {
public TestItem() {
this.Meta = new Meta();
this.Items = new List<int>();
public bool Enabled { get; set; }
public IMeta Meta { get; internal set; }
public List<int> Items { get; set; }
}
public interface ITestItem {
bool Enabled { get; set; }
IMeta Meta { get;}
IList<int> Items { get; set; }
}