Protobuf-Net always deserializes an empty list - c#

The following code shows how I am trying to serialize/deserialze a List using Protobuf-Net. Method getNewItem() returns an object of ItemsStore, which is added to the List.
// Create an empty list
private ItemsStoreList text;
// Add some elements to the list
lock (text.SyncRoot)
{
text.AddItem(getNewItem());
text.AddItem(getNewItem());
text.AddItem(getNewItem());
}
// Serialize
var file = File.Create("testfile.bin");
Serializer.Serialize<ItemsStoreList>(file, text);
// Deserialize
ItemsStoreList textNew = Serializer.Deserialize<ItemsStoreList>(file);
After I run this code, the list contained in object textNew is always empty. Object textNew is instantiated from class ItemsStoreList, which is shown below:
[ProtoContract]
public class ItemsStoreList
{
[ProtoMember(1)]
private List<ItemsStore> m_listData;
private readonly object m_SyncRoot = new object();
public ItemsStoreList()
{
m_listData = new List<ItemsStore>();
}
public void AddItem(ItemsStore item)
{
m_listData.Add(item);
}
public object SyncRoot
{
get { return this.m_SyncRoot; }
}
public int Count
{
get { return m_listData.Count; }
}
public ItemsStore getItem(int idx)
{
return (ItemsStore)m_listData[idx];
}
public void Clear()
{
m_listData.Clear();
}
}
[ProtoContract]
public class ItemsStore
{
[ProtoMember(1)]
public myStruct m_Text;
[ProtoMember(2)]
public ulong m_Time;
public ItemsStore(myStruct newText, ulong newTime)
{
m_Text = newText;
m_Time = newTime;
}
public myStruct Text
{
get { return m_Text; }
}
public ulong Time
{
get { return m_Time; }
}
}
[ProtoContract]
public struct myStruct
{
[ProtoMember(1)]
public uint var1;
[ProtoMember(2)]
public byte var2;
[ProtoMember(3)]
public byte[] var3;
[ProtoMember(4)]
public string var4;
}

The first thing I note is that you have not rewound the stream; adding this (between serialize and deserialize) changes the behaviour:
file.Position = 0;
We now get an exception relating to the ItemsStore constructor, so we can instruct protobuf-net to ignore that constructor completely:
[ProtoContract(SkipConstructor = true)]
public class ItemsStore
Now we get 3 items back:
System.Console.WriteLine(textNew.Count);
which outputs:
3
Further probing shows that it is most likely fetching the other data too:
for (int i = 0; i < textNew.Count; i++)
{
var item = textNew.getItem(i);
System.Console.WriteLine(item.m_Text.var1);
System.Console.WriteLine(item.m_Time);
}
I will, however, add the obligatory warning about mutable structs and public fields.

Related

JSON serialization with class inherited from List<T>

I have a class that inherits from List<T> and add one more class property
public class DrivenList : List<int>
{
public string Name {get;set;}
private DrivenList() { }
public DrivenList(string name) { this.Nname = name; }
}
When JSON serializing the object using Newtonsoft.Json, I get only the list item. ( [1,2,3] )
Any ideas how to add the Name property to the results?
Solved: by adding this attribute to the list
[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
As far as I know with Newtonsoft all you can do is something like this:
[JsonObject(MemberSerialization = MemberSerialization.Fields)]
public class DrivenList : List<int>
{
[JsonProperty]
public string Name { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
}
But this will add you unwanted (maybe) fields.
Personally I will do composition instead of inheritance:
public class DrivenList
{
public string Name { get; set; }
public List<int> Items { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
}
What .NET version are you using and what serializer?
If you are using the standard serializer, then adding [DataMember] annotations would be the answer.
https://msdn.microsoft.com/en-us/library/bb412179(v=vs.110).aspx
But I would suggest to use Json.NET http://www.newtonsoft.com/json
Update:
I would suggest not to directly inherit to List
class Program
{
static void Main(string[] args)
{
var list = new Driven("Ragnarok");
list.Items.Add(1);
list.Items.Add(2);
string json = JsonConvert.SerializeObject(list);
Console.WriteLine(json);
Console.ReadKey();
}
}
public class Driven
{
public Driven(string name)
{
this.Name = name;
}
public List<int> Items { get; set; } = new List<int>();
public string Name { get; set; }
}
Output:
{"Items":[1,2],"Name":"Ragnarok"}
An alternative solution could be to delegate the implementation of IList to your own property. Then you can use the DataContractSerializer. The upside of this is that all the existing C#-code (and all your tests) will still be intact, and no custom logic is needed for serializing it.
If that's not an option and you really want to use NewtonSoft, then you should take a look at this answer, and create your own JsonConverter.
How to serialize/deserialize a custom collection with additional properties using Json.Net
The problem is the following: when an object implements IEnumerable,
JSON.net identifies it as an array of values and serializes it
following the array Json syntax (that does not include properties)
Here's an example that use DataContractSerializer:
JsonHelper from CodeProject
public class JsonHelper
{
/// <summary>
/// JSON Serialization
/// </summary>
public static string JsonSerializer<T>(T t)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream();
ser.WriteObject(ms, t);
string jsonString = Encoding.UTF8.GetString(ms.ToArray());
ms.Close();
return jsonString;
}
/// <summary>
/// JSON Deserialization
/// </summary>
public static T JsonDeserialize<T>(string jsonString)
{
DataContractJsonSerializer ser = new DataContractJsonSerializer(typeof(T));
MemoryStream ms = new MemoryStream(Encoding.UTF8.GetBytes(jsonString));
T obj = (T)ser.ReadObject(ms);
return obj;
}
}
And the new implementation of your class.
[DataContract]
public class DrivenList : IList<int>
{
[DataMember]
public List<int> Items = new List<int>();
[DataMember]
public string Name { get; set; }
private DrivenList() { }
public DrivenList(string name) { this.Name = name; }
#region Implementation of IList
public IEnumerator<int> GetEnumerator()
{
return Items.GetEnumerator();
}
IEnumerator IEnumerable.GetEnumerator()
{
return ((IEnumerable)Items).GetEnumerator();
}
public void Add(int item)
{
Items.Add(item);
}
public void Clear()
{
Items.Clear();
}
public bool Contains(int item)
{
return Items.Contains(item);
}
public void CopyTo(int[] array, int arrayIndex)
{
Items.CopyTo(array, arrayIndex);
}
public bool Remove(int item)
{
return Items.Remove(item);
}
public int Count
{
get { return Items.Count; }
}
public bool IsReadOnly
{
get { return false; }
}
public int IndexOf(int item)
{
return Items.IndexOf(item);
}
public void Insert(int index, int item)
{
Items.Insert(index, item);
}
public void RemoveAt(int index)
{
Items.RemoveAt(index);
}
public int this[int index]
{
get { return Items[index]; }
set { Items[index] = value; }
}
#endregion
}
And an example usage:
var list = new DrivenList("foo");
list.Add(1);
list.Add(3);
list.Add(5);
var json = JsonHelper.JsonSerializer(list);
Output:
{"Items":[1,3,5],"Name":"foo"}
Apply the DataContract attribute for the class and DataMember attribute for the properties.
[DataContract]
public class DrivenList : List<int>
{
[DataMember]
public string Name {get;set;}
private DrivenList() { }
public DrivenList(string name) { this.Nname = name; }
}

Polymorphism and Interfaces in C#

Create three small classes unrelated by inheritance—classes Building, Car and Bicycle. Write an interface ICarbonFootprint with a GetCarbonFootprint method. Have each of your classes implement that interface, so that its GetCarbonFootprint method calculates an appropriate carbon footprint for that class (check out a few websites that explain how to calculate carbon footprints). Write an app that creates objects of each of the three classes, places references to those objects in List, then iterates through the List, polymorphically invoking each object’s GetCarbonFootprint method. Constructor of Car initialize “gallon of gas”, and the Building constructor will initialize buiding-square-footage.
how to calculate carbon-footprint
One gallon of gas yields 20 pounds of CO2 for a car
Multiply the square footage by 50 for a building
None for a bicycle
My instructor's code:
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
list[i].GetCarbonFootprint();
} // end Main
}
My code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Miller
{
class Program
{
static void Main(string[] args)
{
Bicycle bike = new Bicycle();
Building b = new Building();
Car car = new Car();
List<ICarbonFootprint> list = new List<ICarbonFootprint>();
list.Add(bike);
list.Add(b);
list.Add(car);
int totalCarbon = 0;
foreach (var item in list)
{
totalCarbon += item.GetCarbonFootprint();
Console.WriteLine("{0} has a footprint of: {1}", item, item.GetCarbonFootprint());
}
Console.WriteLine("Total footprint is: {0}", totalCarbon);
Console.ReadKey();
}
}
public class Bicycle : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 10;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Building : ICarbonFootprint
{
private string _address;
public string Address
{
get { return _address; }
set { _address = value; }
}
public int GetCarbonFootprint()
{
return 2000;
}
public override string ToString()
{
return string.Format("Building");
}
}
public class Car : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 1500;
}
public override string ToString()
{
return string.Format("Car");
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
}
Me integrating my instructor's code (lines 12-23 changed AKA class Program was the only thing changed):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Miller
{
class Program
{
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
list[i].GetCarbonFootprint();
} // end Main
}
public class Bicycle : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 10;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Building : ICarbonFootprint
{
private string _address;
public string Address
{
get { return _address; }
set { _address = value; }
}
public int GetCarbonFootprint()
{
return 2000;
}
public override string ToString()
{
return string.Format("Building");
}
}
public class Car : ICarbonFootprint
{
private string _make;
private string _model;
public string Make
{
get { return _make; }
set { _make = value; }
}
public string Model
{
get { return _model; }
set { _model = value; }
}
public int GetCarbonFootprint()
{
return 1500;
}
public override string ToString()
{
return string.Format("Car");
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
}
So, replacing my code for class Program with my instructor's code, I received the following errors:
Program.cs(51,23,51,41): error CS1729: 'Miller.Building' does not contain a constructor that takes 1 arguments
Program.cs(52,23,52,34): error CS1729: 'Miller.Car' does not contain a constructor that takes 1 arguments
Now, because the last two days before Spring break were cancelled due to the weather (snow), we weren't able to discuss. My code seems to do what the directions ask, but I would like to get my instructor's code for class Program working with my code. Could someone help me with these errors possibly?
There are a few issues with your code.
First up you need to include the constructors to make the code compile.
For Building this would look like:
private int squareFootage;
public Building(int squareFootage)
{
this.squareFootage = squareFootage;
}
And for Car this would look like:
private int gasGallons;
public Car(int gasGallons)
{
this.gasGallons = gasGallons;
}
Next, you're not following the rules for calculating the carbon footprint.
They should be:
//Bicycle
public int GetCarbonFootprint()
{
return 0;
}
//Building
public int GetCarbonFootprint()
{
return 50 * squareFootage;
}
//Car
public int GetCarbonFootprint()
{
return 20 * gasGallons;
}
Finally, your instructor's code doesn't actually display any results. The code in the for loop should be changed to be Console.WriteLine(list[i].GetCarbonFootprint()); if this is a console app.
So, all up the code should look like this:
public static void Main(string[] args)
{
ICarbonFootprint[] list = new ICarbonFootprint[3];
// add elements to list
list[0] = new Bicycle();
list[1] = new Building(2500);
list[2] = new Car(10);
// display carbon footprint of each object
for (int i = 0; i < list.Length; i++)
Console.WriteLine(list[i].GetCarbonFootprint());
}
public class Bicycle : ICarbonFootprint
{
public string Make { get; set; }
public string Model { get; set; }
public int GetCarbonFootprint()
{
return 0;
}
}
public class Building : ICarbonFootprint
{
private int squareFootage;
public Building(int squareFootage)
{
this.squareFootage = squareFootage;
}
public string Address { get; set; }
public int GetCarbonFootprint()
{
return 50 * squareFootage;
}
}
public class Car : ICarbonFootprint
{
private int gasGallons;
public Car(int gasGallons)
{
this.gasGallons = gasGallons;
}
public string Make { get; set; }
public string Model { get; set; }
public int GetCarbonFootprint()
{
return 20 * gasGallons;
}
}
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
I've opted to short-cut the property definitions rather than implement them with fields.
The output is:
0
125000
200
You should write constructors for Building and Car like next:
public Building(int MyValue)
{
...
}
and your code will work fine.
Suggestion: Car and Bicycle shares properties, and the ICarbonFootprint implementation, so you can create a base class with an abstract method. Also the GetCarbonFootprint from ICarbonFootprint interface must be type of System.Double.
public interface ICarbonFootprint
{
int GetCarbonFootprint();
}
public class Building : ICarbonFootprint
{
public int BuildingSquareFootage { get; set; }
public string Address { get; set; }
public Building(int buildingSquareFootage, string address)
{
BuildingSquareFootage = buildingSquareFootage;
Address = address;
}
public int GetCarbonFootprint()
{
return BuildingSquareFootage * 50;
}
public override string ToString()
{
return string.Format("Building");
}
}
public abstract class CarBicycleBase : ICarbonFootprint
{
public string Make { get; set; }
public string Model { get; set; }
protected CarBicycleBase(string make, string model)
{
Make = make;
Model = model;
}
public abstract int GetCarbonFootprint();
}
public class Bicycle : CarBicycleBase
{
public Bicycle(string make, string model)
: base(make, model) { }
public override int GetCarbonFootprint()
{
return 0;
}
public override string ToString()
{
return string.Format("Bike");
}
}
public class Car : CarBicycleBase
{
public int GallonOfGas { get; set; }
public Car(int gallonOfGas, string make, string model)
: base(make, model)
{
GallonOfGas = gallonOfGas;
}
public override int GetCarbonFootprint()
{
return GallonOfGas * 20;
}
public override string ToString()
{
return string.Format("Car");
}
}
Example:
...
var list = new List<ICarbonFootprint>(3)
{
new Car(10, "...", "..."),
new Bicycle("...", "..."),
new Building(20, "...")
};
foreach (ICarbonFootprint item in list)
item.GetCarbonFootprint();
...
I hope it helps.

Detecting changes within serializable data classes in C#

I've been experimenting with detecting changes in plain objects in C#. The aim being to have a container-type class for a bunch of data objects that can react when any one of them changes. For fun I wanted to see if all the work could be done in the container class, rather than resort to properties and dirty flags or events on the objects themselves.
What I'm curious about is whether there is a smart, fast and efficient way of doing this. My attempt is below, and it's none of those (the 'CheckStates' method would need to be called every frame for a start!) I've restricted it to only allow one instance per type, which suits my needs.
Note that an object passed in might be as follows:
[Serializable]
public class PlayerInfo
{
public string name = string.Empty;
public int score = 0;
}
Then the container:
public class AppState
{
private class StateData
{
public System.Object instance = null;
public Byte[] currentState = new Byte[0];
public Byte[] previousState = new Byte[0];
}
private Dictionary<Type, StateData> _allStates = new Dictionary<Type, StateData>();
private BinaryFormatter _formatter = new BinaryFormatter();
private MemoryStream _memoryStream = new MemoryStream();
public T GetState<T>() where T : class, new()
{
T state = default(T);
var stateType = typeof(T);
StateData stateData;
if(_allStates.TryGetValue(stateType, out stateData))
{
state = ReadData<T>(stateData);
}
else
{
var newState = CreateData<T>(out state);
_allStates[stateType] = newState;
}
return state;
}
public void CheckStates()
{
foreach(var state in _allStates)
{
if(HasChanged(state.Value))
{
Console.WriteLine(state.Key.ToString() + " has changed");
UpdateState(state.Value);
}
}
}
private StateData CreateData<T>(out T instance) where T : class, new()
{
instance = new T();
var stateData = new StateData();
stateData.instance = instance;
_formatter.Serialize(_memoryStream, instance);
var bytes = _memoryStream.ToArray();
stateData.currentState = bytes;
stateData.previousState = bytes;
return stateData;
}
private T ReadData<T>(StateData data) where T : class, new()
{
return data.currentState as T;
}
private bool HasChanged(StateData data)
{
_memoryStream.Position = 0;
_formatter.Serialize(_memoryStream, data.instance);
var current = _memoryStream.ToArray();
var previous = data.previousState;
if(current.Length != previous.Length)
{
return true;
}
for(int i = 0; i < current.Length; ++i)
{
if(current[i] != previous[i])
{
return true;
}
}
return false;
}
private void UpdateState(StateData data)
{
_memoryStream.Position = 0;
_formatter.Serialize(_memoryStream, data.instance);
data.previousState = _memoryStream.ToArray();
}
}
Alternatives I could think of were:
use structs instead of serializable classes (being forced to pass by value would mean that any change would have to go through a 'set' method on the container)
have the AppState's 'GetState' method return an IDisposable wrapper, which on Dispose could trigger a check for changes on that type (only problem is that there's nothing to stop someone from storing a reference to the object and modifying it without the container knowing)
EDIT: should add that it doesn't need to be thread-safe
I don't regard serializable classes as POCO, because you're engineering the classes so that they work with your change detection mechanism. So I wouldn't call them plain.
Your alternatives:
use structs instead of serializable classes
Don't use mutable structs Why are mutable structs “evil”?. And if your struct is immutable, then you might as well pass by reference, i.e. have a class.
have the 'get' method return an IDisposable wrapper
I'm not sure what get method you are referring to.
Proxy
One alternative is to allow a descendant proxy to react to calls to the setters:
public class PlayerInfo
{
public virtual string Name { get; set; }
public virtual int Score { get; set; }
}
public class PlayerInfoDetection : PlayerInfo
{
public int Revision { get; private set; }
public override string Name
{
set
{
base.Name = value;
Revision++;
}
}
public override int Score
{
set
{
base.Score = value;
Revision++;
}
}
}
private static void Example()
{
PlayerInfo pi = new PlayerInfoDetection();
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
pi.Name = "weston";
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
pi.Score = 123;
Console.WriteLine(((PlayerInfoDetection)pi).Revision);
}
This is how NHibernate "watches" objects fetched from the database, and why every object property must be virtual in NHibernate.
Aspect orientated
The same could be achieved with a product like post sharp where you could annotate your class to tell it when the revision must be changed.
public class PlayerInfo
{
public int Revision { get; private set; }
public string Name { get; [IncreaseRevision] set; }
public int Score { get; [IncreaseRevision] set; }
}
Making use of a well implemented hash function
Hash functions should not change their value while the object is in a container such as a hash set. We can make use of this to detect changes.
Drawback Note that any Hash collisions will yield incorrect results. This includes duplicates.
[TestClass]
public class ChangeDetectUnitTest
{
public class ChangeDetectList<T>
{
private readonly List<T> list = new List<T>();
private readonly ISet<T> hashes = new HashSet<T>();
public bool HasChanged(T t)
{
return !hashes.Contains(t);
}
public void Add(T t)
{
list.Add(t);
hashes.Add(t);
}
public void Reset()
{
hashes.Clear();
foreach (var t in list)
hashes.Add(t);
}
}
public class PlayerInfo
{
public string Name { get; set; }
public int Score { get; set; }
public override int GetHashCode()
{
//every field that you want to detect must feature in the hashcode
return (Name ?? "").GetHashCode() * 31 + Score;
}
public override bool Equals(object obj)
{
return Equals(obj as PlayerInfo);
}
public bool Equals(PlayerInfo other)
{
if (other == null) return false;
return Equals(other.Name, Name) && Score == Score;
}
}
private ChangeDetectList<PlayerInfo> list;
[TestInitialize]
public void Setup()
{
list = new ChangeDetectList<PlayerInfo>();
}
[TestMethod]
public void Can_add()
{
var p1 = new PlayerInfo();
list.Add(p1);
Assert.IsFalse(list.HasChanged(p1));
}
[TestMethod]
public void Can_detect_change()
{
var p1 = new PlayerInfo();
list.Add(p1);
p1.Name = "weston";
Assert.IsTrue(list.HasChanged(p1));
}
[TestMethod]
public void Can_reset_change()
{
var p1 = new PlayerInfo();
list.Add(p1);
p1.Name = "weston";
list.Reset();
Assert.IsFalse(list.HasChanged(p1));
}
}

C#: Confusion about Interfaces, Implementation and Inheritance

I'm wondering about what's the way to go, if I need to publicate data-interfaces but want to use them internal with extended calculated properties. To make it clearer:
// The public interface
public interface IData
{
int Property { get; }
}
// The internal interface
internal interface IExtendedData : IData
{
int ExtendedProperty { get; }
}
// The assumed implementation of someone using my interface
public class Data : IData
{
public Data(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public override string ToString()
{
return Property.ToString();
}
}
// My implementation
internal class ExtendedData : IExtendedData
{
public ExtendedData(int a)
{
Property = a;
}
public int Property
{
get;
private set;
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
public override string ToString()
{
return Property.ToString() + ExtendedProperty.ToString();
}
}
// publicated by me, for the person who uses my dll
public static class Calculations
{
public static int DoSomeCalculation(IData data, int parameter)
{
// This probably don't work, but maybe shows what I want to do
IExtendedData tempData = (ExtendedData)data;
return tempData.ExtendedProperty * parameter;
}
}
I'm realy frustrated, cause I feel like missing some basical programing skills.
You could solve this problem by implementing ExtendedData as a Wrapper for a class implementing IData
internal class ExtendedData : IExtendedData
{
private IData data;
public ExtendedData(IData data)
{
this.data = data;
}
public int Property
{
get { return data.Property; }
private set { data.Property = value; }
}
public int ExtendedProperty
{
get
{
return 2 * Property;
}
}
}
and use this in DoSomeCalculation like
IExtendedData tempData = new ExtendedData(data);
ExtendedData could inherit from Data:
class ExtendedData : Data
{...}
And for creation of a Data object you add a factory like so:
public class DataFactory
{
public IData CreateData()
{
return new ExtendedData();
}
}
User have to create all its Data objects by this factory. You can ensure it by making Data's constructor internal.
In your DLL you can then cast to ExtendedData.

Should data classes which are passed by a webservice be attributes with [Serializable]

I want to transfer some data classes via Webservice:
public class MyClass
{
public int Int { get; set; }
public MyClass(int v)
{
Int = v;
}
private MyClass()
{
}
}
public enum MyEnum
{
One = 7,
Two = 13,
Three = 15
}
public class TestDataClass
{
private int _someInt;
public List<MyClass> Values { get; set; }
public int SomeInt
{
get
{
return _someInt + 10;
}
set { _someInt = value; }
}
public TestDataClass(int someInt)
{
SomeInt = someInt;
Values = new List<MyClass>();
for (int i = 0; i < 10; i++)
{
Values.Add(new MyClass(i));
}
}
private TestDataClass() {}
}
TestDataClass is the class beening passed, what should be attributed with serializable?
Thanks, Alex.
If you want to use the (old) ASMX style webservice: Yes.
When using WCF: No, use [DataContract] instead.
In both cases, you need attributes for the main class and for any embedded type that is not already Serializable or a 'known type'.

Categories