In my class (Camera), that I need to serialize, I have one member which doesn't have much serialization means and I can't modify its class. But there are only 2-3 parameters out of whole class that I can serialize and then de-serialize based on that.
XmlSerializer SerializerObj = new XmlSerializer(typeof(Camera));
TextWriter WriteFileStream = new StreamWriter(#"C:\test.xml");
SerializerObj.Serialize(WriteFileStream, cc);
WriteFileStream.Close();
How and where can I put custom serialization code, to take those 2-3 parameters from object and give to serializer, then during de-serialization create again that object using those 2-3 parameters.
Update. The example code:
[Serializable()]
public class Camera
{
public string name;
public int index;
public double distance;
public List<string> CameraList { get; set; }
[XmlIgnore()]
public GMarkerGoogle marker;
public Camera()
{
}
}
marker is the member that doesn't have serialization means. But there with marker.position, marker.rotation I can re-create that object.
If you can't or don't want to Xml serialize your GMarker then make sure that you do serialize the properties needed to reconstruct it (kind of what you already suggested). That way you can make a property with backing field to lazy recreate the GMarker.
[Serializable()]
public class Camera
{
public string name;
public int index;
public double distance;
public List<string> CameraList { get; set; }
private GMarkerGoogle _marker;
[XmlIgnore()]
public GMarkerGoogle Marker
{
set
{
_marker = value;
MarkerPosition = _marker.position;
MarkerRotation = _marker.rotation;
}
get
{
if (_marker == null)
{
_marker = new GMarkerGoogle(MarkerPosition, MarkerRotation);
}
return _marker;
}
}
public double MarkerPosition { get; set; }
public double MarkerRotation { get; set; }
public Camera()
{
}
}
Does this help? I made up a thing or two because I don't know the API for the marker, but I hope you can draw the picture from this point onwards.
By implementing the IXmlSerializable interface in your Camera class.
Check MSDN for more info.
Alternatively you could use the [XmlIgnore] attribute to flag the properties you do not want to serialize to XML.
Check MSDN for more info :).
PS: If you post some code I can show you an example but you probably don't need me. Let me know if you do though.
Related
I'm writing a new DataContract to our service (which is in windows service and exposed by iis). in the main class i have an Arraylist member that when i expose i get System.Runtime.Serialization.InvalidDataContractException if i change the member to "List<>" then all is great (and it goes through from postman->iis->windows service).
the class is:
namespace Kitchen
{
[Serializable()]
[DataContract]
[KnownType(typeof(Fruit))]
[XmlInclude(typeof(Fruit))]
public class Foods
{
private ArrayList uniFood;
private List<string> lstCity;
[DataMember]
[XmlElement(typeof(Fruit))]
public ArrayList FoodArr
{
get
{
return uniFood;
}
set
{
uniFood = value;
}
}
[DataMember]
[XmlIgnore]
public List<string> CityGrown
{
get
{
return lstCity;
}
set
{
lstCity = value;
}
}
[DataMember]
[XmlIgnore]
public bool IsMerge
{
get;
set;
}
[DataMember]
[XmlIgnore]
public bool IsRipe
{
get;
set;
}
public Foods()
{
uniFood = new ArrayList();
lstCity = new List<string>();
}
}
}
the error i get when trying to send class to service reference:
System.Runtime.Serialization.InvalidDataContractException: Type 'Newtonsoft.Json.Linq.JToken' is a recursive collection data contract which is not supported. Consider modifying the definition of collection 'Newtonsoft.Json.Linq.JToken' to remove references to itself.
any help would be appreciated
This is a new feature in api, working on vs2013. in the past i've tried changing the arraylist to List<> and that helps but i need it as array list because when serializing to xml it comes out as:
Please use [CollectionDataContract(...)] attribute instead of [DataContract] attribute when Data Contract class has an collection member, please refer to the below document.
https://learn.microsoft.com/en-us/dotnet/framework/wcf/feature-details/collection-types-in-data-contracts
https://learn.microsoft.com/en-us/dotnet/api/system.runtime.serialization.collectiondatacontractattribute?redirectedfrom=MSDN&view=netframework-4.8
I have multiple web requests that post JSON object and I have serializable classes with all the fields. For example:
[Serializable]
public class RequestOne()
{
public string date;
public string information;
public string subject;
}
[Serializable]
public class RequestTwo()
{
public int ID;
public string Data;
public string message;
}
And my method takes partially filled request class and I want to fill in any missing fields with default values declared in constant class.
And I want to avoid writing each method with for each request, like :
public static void FillWithDefault(this RequestOne request)
{ if (request.date.Equals(null)) request.date = DEFAULT_DATE;
if (request.information.Equals(null)) request.information = DEFAULT_INFO;
if (request.subject.Equals(null)) request.subject = DEFAULT_SUBJECT;
}
public static void FillWithDefault(this RequestTwo request)
{
//do the same for the fields in RequestTwo
}
I want to know if there is any way to achieve this using generic?
I want to do something similar to this:
public static void FillWithDefault<T>(this T request)
{
if(typeof(T) == typeof(request))
{
//check each member in request and fill with default if it's null
}
.
.
.
}
So that in my main method I can use like this :
RequestOne request = new RequestOne();
request.FillWithDefault();
RequestTwo request2 = new RequestTwo();
request2.FillWithDefault();
Can someone please help with idea on this? Am I overthinking on this? I'm new to generic so please feel free to advise on my code.
Edit
Sorry guys, I did not mention that I will be using this method for test automation. Those request contracts cannot be changed since it's by design. Sorry again for the confusion!
Use constructors. Also make use of properties. Don't gather the default filling code to one place, it's the responsibility of the classes so keep them there.
[Serializable]
public class RequestOne()
{
public string date { get; set; };
public string information { get; set; };
public string subject { get; set; };
public RequestOne()
{
Date = DEFAULT_DATE;
Information = DEFAULT_DATE;
Subject = DEFAULT_SUBJECT;
}
}
[Serializable]
public class RequestTwo()
{
public int ID { get; set; };
public string Data { get; set; };
public string Message { get; set; };
public RequestTwo()
{
Data = DEFAULT_DATA;
message = DEFAULT_MESSAGE;
}
}
Generics are used when the types have common operations/properties defined so you can apply the same routine for each type in one place instead of declaring different methods for each type.
However in this case, you have two different types with different properties, so I would not use generics here. You can achieve it with manual type checking and using reflection to get properties and set them but it's not a good way and definitely wouldn't be a good usage of generics.
Overloading is the way to go.
you can use property
[Serializable]
public class RequestOne()
{
private string _date;
public string date { get { return _date;} set { _date = value ?? DEFAULT_DATE; }};
public string information; // same here
public string subject; //same here
}
In our application, we have a Money type, which contains an amount (decimal) and a currency code (string). In simple form, it looks like this:
public class Money
{
public decimal Amount{get;set;}
public string CurrencyCode{get;set;}
}
As you might imagine, this gets used in many places in the application, and is frequently serialized/deserialized as it is sent to/from the client. The Money amount is typically serialized as a compound value, e.g. "1.23USD" to represent $1.23. The old client (HTML/JS) would parse that value into its component parts back into the Money type. Money values are sent as element values, and as attribute values, depending on where they are in the app, e.g:
<SomeClass moneyValue="1.23USD" ... />
or
<SomeClass>
<MoneyValue>1.23USD</MoneyValue>
...
</SomeClass>
I am trying to figure out a way that I can use the built-in C#/.NET Xml Serialization tools to have this same sort of behavior. I looked at implementing ISerializable, but haven't been able to figure out quite the correct way to do so.
Essentially, I want to be able to have the Money amount deserialized by custom logic of my own (that knows how to parse "1.23USD" into a Money amount), and serialize it to the simple string, e.g. "1.23USD"
The end goal would be to able to have the Money amount in a class as either:
[XmlAttribute]
public Money SomeField // SomeField='123.USD
or:
[XmlElement]
public Money SomeOtherField //<SomeOtherField>1.23USD</SomeOtherField>
just the same way you can do that with simple types like int, string, double, etc.
Is this possible?
Turns out there really wasn't a good 100% answer to this - the problem is that you can't serialize the complex type (e.g. Money) to an attribute, even if you serialize it to a simple string. So no matter what, I can't have someAttribute='1.23 USD' that is reusable in a general way.
So...the posted answer is a nice workaround for Attributes, and for places where I used Money as an element, I just implemented IXmlSerializable to output the compound field and re-split it on parse. This way, no wrappers are required, it just works.
public struct Money : IXmlSerializable
{
public double Amount { get; set; }
public string CurrencyCode { get; set; }
public System.Xml.Schema.XmlSchema GetSchema()
{
return (null);
}
public void ReadXml(System.Xml.XmlReader reader)
{
reader.MoveToContent();
Boolean isEmptyElement = reader.IsEmptyElement; // (1)
reader.ReadStartElement();
if (!isEmptyElement) // (1)
{
var str = reader.ReadContentAsString();
string[] sa = str.Split(' ');
Amount = double.Parse(sa[0]);
CurrencyCode = sa[1];
reader.ReadEndElement();
}
}
public void WriteXml(System.Xml.XmlWriter writer)
{
writer.WriteString(Amount + " " + CurrencyCode);
}
}
And for attributes, the posted answer works as well, thank you.
The following code does the trick:
public class Money
{
public decimal Amount { get; set; }
public string CurrencyCode { get; set; }
}
public class SomeClass
{
public SomeClass() { }
[XmlIgnore]
public Money WrappedMoney { get; set; }
[XmlAttribute]
public string moneyValue
{
get
{
return String.Format("{0:.##}{1}", WrappedMoney.Amount, WrappedMoney.CurrencyCode);
}
}
}
public class ParentClass
{
public SomeClass SomeClass {get; set;}
}
class Program
{
public static int Main(string[] args)
{
var parent = new ParentClass
{
SomeClass = new SomeClass
{
WrappedMoney = new Money { Amount = 1.25M, CurrencyCode = "USD" }
}
};
var serializer = new XmlSerializer(typeof(ParentClass));
using (var writer = new StreamWriter("output.xml"))
{
serializer.Serialize(writer, parent);
}
return 0;
}
}
Xml output is:
<?xml version="1.0" encoding="utf-8"?>
<ParentClass xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<SomeClass moneyValue="1.25USD" />
</ParentClass>
I have a class called MyBoard that looks like this
Public MyBoard
{
private BoardTile[,] tiles;
private bool tilesEliminated;
public int blabla {get; set; }
}
If i understand correctly the Serializable attribute serializes the entire class, what I'm attempting to do is to have the ability to serialize only the fields i want into XML format (other fields are irrelevant)
In my case i would like to write something that looks like this :
[ISerializable]
Public MyBoard
{
[SerializeMe]
private BoardTile[,] tiles;
private bool tilesEliminated;
public int blabla {get; set; }
}
I want to choose with some attribute what to serialize and what not, more over inside the class "BoardTile" i would like to do the same thing and choose the relevant fields also.
And then write something like this
main()
{
MyBoard m = new MyBoard();
//fill the tiles somehow.
m.SerializeToXml();
}
If i understand correctly i need to write a custom serializer by myself by inheriting ISerializable, but maybe it's possible to avoid it and letting .Net to serialize by himself automatically with some attributes that i don't know about.
By the way it's important to me that the output will be XML so i could read it.
I hope you understand my question, thanks for you help :)
Use DataContract attribute and XmlSerializer class:
[DataContract]
Public MyBoard
{
[DataMember]
pricate BoardTile[,] tiles;
private bool tilesEliminated;
public int blabla {get; set; }
}
And serialization:
var board = new MyBoard();
var ser = new DataContractSerializer(typeof(MyBoard));
var sw = new StringWriter();
ser.WriteObject(sw, board);
sw.Close();
var xml = sw.ToString();
It will serialize only members that are marked with [DataMember] attribute and skip the other ones.
I am trying to create a simple in-memory grid that can be serialized using protocol buffers.
The idea is the user can create/define columns of any type (primitives or user defined as long as they're protocol buffers tagged).
My problem is you can't serialize Type data with protocol buffers so how can i achieve this?
Code is below showing how i'd hoped to code the Columns of the grid.
Thanks a lot.
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
Column colOrderId = new Column("OrderId", typeof(uint));
Column colOrderDesc = new Column("OrderDesc", typeof(string));
Column colPrice = new Column("Price", typeof(Price));
Column colOrderDateTime = new Column("OrderDateTime", typeof(DateTime));
var s = colOrderId.ToBArray();
}
}
[ProtoContract, Serializable]
public sealed class Column
{
public Column(string name, Type type)
{
Name = name;
Type = type;
}
[ProtoMember(1)]
public string Name { get; private set; }
[ProtoMember(2)]
public Type Type { get; private set; }
}
[ProtoContract, Serializable]
public sealed class Price
{
public Price(double value, string currency)
{
Value = value;
Currency = currency;
}
[ProtoMember(1)]
public double Value { get; private set; }
[ProtoMember(2)]
public string Currency { get; private set; }
}
public static class ProtoBufEx
{
public static byte[] ToBArray<T>(this T o)
{
using (MemoryStream ms = new MemoryStream())
{
ProtoBuf.Serializer.Serialize(ms, o);
return ms.ToArray();
}
}
}
There's a couple of issues in this approach; yes, in standard protocol buffers any kind of Type metadata is a bit naughty, as it isn't really interoperable, but I play a little loose with that in v2 on an opt-in basis - allowing you to send object etc as long as internally it still knows what you mean.
This, however, will get expensive for cell-by-cell work, even with the optimisations built in (it only sends the same type meta once, for example).
IMO, though, a far better option is to restrict yourself to a list of known types that are all known ahead of time. If you can do that there are some interesting tricks with inheritance that are pretty efficient and reasonably suited for this scenario. But essentially you'd have something like:
[ProtoContract]
[ProtoInclude(4, typeof(Column<int>))] // etc
abstract class Column {
[ProtoMember(1)]
public string Name {get;private set;}
public abstract object Value {get;private set;}
}
[ProtoContract]
class Column<T> : Column {
[ProtoMember(1)]
public T TypedValue { get;private set;}
override Value {...shim to TypedValue...}
}
// etc
(pseudo-code, incomplete)
I'd happily walk you through a lot of that, but you might also want to look at this blog entry to see if using DataTable (much as I dislike it for data-access) might save some effort here.