How do you serialize/deserialize jagged/nested arrays with protobuf-net? - c#

In his answer to For which scenarios is protobuf-net not appropriate? Marc mentions:
jagged arrays / nested lists without intermediate types aren't OK - you can shim this by introducing an intermediate type in the middle
I'm hoping this suggests there is a way to do it without changing my underlying code, maybe using a surrogate?
Has anybody found a good approach to serializing/deserializing a nested/jagged array

At the current time, it would require (as the message suggests) changes to your model. However, in principal this is something that that the library could do entirely in its own imagination - that is simply code that I haven't written / tested yet. So it depends how soon you need it... I can take a look at it, but I can't guarantee any particular timescale.

A solution might be to serialize an intermediate type, and use a getter/setter to hide it from the rest of your code.
Example:
List<double[]> _nestedArray ; // The nested array I would like to serialize.
[ProtoMember(1)]
private List<ProtobufArray<double>> _nestedArrayForProtoBuf // Never used elsewhere
{
get
{
if (_nestedArray == null) // ( _nestedArray == null || _nestedArray.Count == 0 ) if the default constructor instanciate it
return null;
return _nestedArray.Select(p => new ProtobufArray<double>(p)).ToList();
}
set
{
_nestedArray = value.Select(p => p.MyArray).ToList();
}
}
[ProtoContract]
public class ProtobufArray<T> // The intermediate type
{
[ProtoMember(1)]
public T[] MyArray;
public ProtobufArray()
{ }
public ProtobufArray(T[] array)
{
MyArray = array;
}
}

Related

Casting contents of an indexer's returned collection?

I have a table/row/column data structure setup. There is a string-based indexer in the DtaTable class to return DtaRows, and another on the DtaRow class to return DtaColumns. So you can write things like...
return theTables["tablename"]["rowidentifier"]["columnname"];
In actuality, the objects inside the tables are not DtaRows, but one of about three dozen subclasses, like InflationRow and CurrencyRow. Each table contains only objects of those types, so for instance...
theTables["Inflations"]["General"];
always returns an InflationRow.
Now to make this easier to access from C#, I have a bunch of methods at a higher level like...
public DtaTable Inflations { get {return pTables["Inflations"];} }
Now the problem I'd like to solve is that when someone calls one of these methods, they don't get an InflationRow, because DtaTable has DtaRows. So for instance...
MyInfRow = Inflations["General"];
returns a DtaRow. So I have to cast all the time...
MyInfRow = (InflationRow)Inflations["General"];
I want to get rid of all the casting.
The only solution I have found so far is to make 36 new subclasses of the table object, each overriding the indexer return type. This seems worse than the casting.
Is there some simpler way to do this?
It you know that callers are only primarily going to use another indexer, you can introduce a generic class providing that:
public class SpecializedTable<T>
{
private readonly DtaTable table;
// Just in case anyone really wants this
public DtaTable Table { get; }
public SpecializedTable(DtaTable table)
{
this.table = table;
}
public T this[string row] { get { return (T) (object) table[row]; } }
}
As an aside, these DtaTable etc names feel annoying unpronounceable / easily confusable with the .NET DataTable classes. If you're in a position to rename them, I'd suggest you do so.
Then your Inflations property can be:
public SpecializedTable<InflationRow> Inflations
{
get
{
return new SpecializedTable<InflationRow>(pTables["Inflations"]);
}
}
You may want to cache this to avoid creating a new object each time you call the property though.
At that point, this code: Inflations["General"] will perform the cast appropriately for you.
Use as instead of direct cast. If casting is valid it will return the instance, otherwise it will stay as NULL.
public MyInfRow Inflations { get {return pTables["Inflations"] as MyInfRow } }

How to avoid boxing and if or Switch statements

Suppose I have following object:
object[] objs = new object[3]{ "this is sample string", 42L, 1};
and I want to do something to the individual objects in the array like
foreach (object o in objs)
{
/// logic here
mylogic();
}
Now mylogic() will only take object parameters so there is boxing going on, but we require to be able to do something based on the type of the object, so we would do something like :
public void dosomething(object obj)
{
// one way
if(obj.GetType() == typeof(string))
{
// string specific something
}
// another way
if(obj is long)
{
// long specific something
}
}
Well it's ugly and non performance, is there a better way possible using generics or any other way?
Your values are already boxed, because they are stored in an object[]. So no additional boxing takes place when you pass them to a method taking an object argument.
The object[] is where I would aim my focus - is it really necessary to represent your data like that? Do you really not know their structure? It would be preferable to define a class (or a structure) to hold your data, and also to contain the methods that act on the data - then you know a type of each field or property at design and compile time, and you can use this information in further code. In your case that might look like:
class Container
{
public string StringProperty { get; set; }
public long LongProperty { get; set; }
public int IntProperty { get; set; }
public void DoSomething()
{
// string specific something with StringProperty
// long specific something with LongProperty
// int specific something with IntProperty
}
}
That way you begin to encapsulate your data and make sure it is located close to the logic that uses them. Even better might be to make the properties into private readonly fields, so they are not even visible to the outside.
You could try looking into using the dynamic keyword in C# 4.0 and later and see if that helps you. It would be better to define your own class and make properties of the different types and just use those instead.
The memory overhead would be minimal and you'd avoid all the boxing penalties.
IMO, in such cases one should ask the question: is there anything wrong with the code design? What is the idea of the array containing different types of objects? What do they represent? May be you need a separate class that holds these different objects...

Inheriting a List<> in c# and overriding the constructor

I'm trying to create a wrapper around List to do some specific things I want, such as compute max min, extract specific values from some elements, etc.
I start with
public struct datum {
public UInt32[] chan;
public UInt64 sample_number;
public UInt32 time;
public UInt32 source_sector;
}
public class dataSet : List<datum> {
bool dirty=true;
....
}
the methods are typically like this (I want to know if the list has been modified as I have a max()/min() function that only parses the data when it has been modified and caches the values to reuse if the List has not been modified)
public new void Add(datum x ) {
base.Add(x);
this.dirty = true;
}
However, I'm not sure how to create a constructor. This syntax does not work.. how can I get this type of behavior?
public dataSet(int count) {
this = (dataSet) new List<datum>(count);
}
I also have this constructor, which seems to work fine (no compilation errors) though untested
public dataSet(List<datum> data) {
this.AddRange(data);
}
I came across a post that said that you should use a Collection and a List is used for speed. Though I need the speed, and I'm not sure why a Collection would be better?
--UPDATE--
I don't want to use linq as you can't create something that computes max/min simultaneously as efficiently as this:
public void recalculateMaxMin() {
foreach (var d in data) {
for (int i = 0; i < 16; i++) {
if (d.chan[i] > max[i]) max[i] = d.chan[i];
if (d.chan[i] < min[i]) min[i] = d.chan[i];
}
}
}
Thnx
I'm trying to create a wrapper around List to do some specific things I want, such as compute max min, extract specific values from some elements, etc.
Don't. Just use LINQ to Objects. That's what it was designed for:
var list = new List<int> { 10, 20, 30 };
var average = list.Average();
var max = list.Max();
// etc
In general, I would advise against deriving from List<T> anyway - that's not what it was designed for. However, if you must, you just chain from one constructor to a base constructor:
public dataSet(int count) : base(count)
{
// Add in any extra code you want to here. Probably none in this case.
// It would execute *after* the base constructor call.
}
See my article on constructors for more information about constructor chaining.
(I'd also strongly advise you to change the name - dataSet doesn't comply with .NET naming conventions, and DataSet would mean something else entirely to most .NET developers.)
You can never ever set "this" to something in C#. I think you are looking for this:
public dataSet(int count)
: base(count)
{ }
However in my opinion you should take a look at "System.Linq" namespace. I think what you are trying to implement has been done before by Microsoft. 'Select', 'Join', 'Where' and many other clauses has been already implemented in Linq. Also you can use "INotifyCollectionChanged" interface to implement the dirty thing.
Here are some references:
INotifyCollectionChanged
Linq
If you realy need to implement a complete List class with a new behavior, implementing "System.Collections.Generic.IList" interface is the only thing that will rock your idea in an advanced and perfect way. It's more customizable than inheriting from the List class and trying to change everything you have no access to.
Hope it helps
Cheers
public dataSet(int count)
: base(count) {
}
You can call the base type's constructor using base()
public dataSet(int count) : base(count)
{
// no need to implement anything here. base(count) will call the base
// type's constructor
}

Encapsulation questions in C#

I'm having some problems with encapsulation in C#. There are two specific scenarios that are causing me problems and I believe the issue is related.
Scenario #1
I have a class definition that looks something like this
class MyClass
{
private int _someField;
private OtherClass _otherClass;
public int someField
{
get { return _someField; }
set { _someField = value; }
}
public OtherClass otherClass
{
get { return _otherClass; }
set { _otherClass = value; }
}
}
If I then try and do something like this in a new piece of code
MyClass theClass = new MyClass();
theClass.otherClass.XYZ += 1;
I get told Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
Scenario 2#
public partial class trksegType
{
private wptType[] trkptField;
private extensionsType extensionsField;
/// <remarks/>
[System.Xml.Serialization.XmlElementAttribute("trkpt")]
public wptType[] trkpt
{
get
{
return this.trkptField;
}
set
{
this.trkptField = value;
}
}
}
If I now try and foreach through the wptType array:
foreach (wptType way in trk.trkseg[i])
I get told - foreach statement cannot operate on variables of type 'trksegType' because 'trksegType' does not contain a public definition for 'GetEnumerator'
Even though an array should implicitly allow enumeration.
Can anyone explain what's going on and what I can do to get around this problem, whilst still maintaining best practices.
For scenario 1, I suspect that OtherClass has been defined as a struct. When a struct is accessed from a property accessor a new copy of the struct is created and returned (structs are value types). Changing a property on this new copy will have no effect on the original struct.
The C# compiler detects this and raises that slightly obscure error.
Scenario 1:
The reason is very likely because your OtherClass is a struct and not a class. Value sematics are a bit tricky and mutable value types are considered harmful. So you either want to make OtherClass a class and not a struct or you do something along those lines:
struct OtherClass
{
public int XYZ { get; }
public OtherClass(int xyz)
{
XYZ = xyz;
}
public OtherClass AddToXYZ(int count)
{
return new OtherClass(this.XYZ + count);
}
}
Then you can do
myClass.otherClass = myClass.otherClass.AddToXYZ(1);
Scenario 2:
You either need to implement IEnumerable on trksegType to enumerate over trkpt or actually access trkpt for the enumeration.
In General:
You have violated encapsulation in both scenarios by accessing objects through other objects. Have a look here: http://www.csharp-station.com/Tutorials/lesson19.aspx
You also should consider using better (more explicit) names for your objects. mttng vwls ds nt ncrs rdblty.
(You really shouldn’t post two questions in one.)
Scenario 1
Cannot Modify the return value of 'MyClass.otherClass' because it is not a variable.
This error happens because OtherClass is not a class, but a struct — also called a value type. This means that accessing MyClass.otherClass copies the value instead of returning a reference. You would be modifying this copy, which would be pointless. The compiler catches this because it is always a bug and never useful.
Scenario 2
foreach (wptType way in trk.trkseg[i])
You haven’t told us what trkseg[i] is, but if it is of the type trksegType, then the answer is: because trksegType doesn’t allow any enumeration. It does not implement IEnumerable, IEnumerable<T>, nor does it have a GetEnumerator method of its own.
Perhaps you meant to write:
foreach (wptType way in trk.trkseg[i].trkpt)
because trkpt is an array of wptType. (You might have found this error sooner if you used more meaningful variable names instead of weird combinations of letters that make no sense.)
I can't see anything wrong with your first example - so double check that the sample that errors really does and correct if not.
In the second instance, it looks like you're trying to iterate on an instance of trksegType, rather than the contained trkpt property. Try foreach (wptType way in trk.trkseg[i].trkpt) instead.

How can we differentiate between SDK class objects and custom class objects?

To give an idea of my requirement, consider these classes -
class A { }
class B {
String m_sName;
public String Name {
get { return m_sName; }
set { m_sName = value; }
}
int m_iVal;
public int Val {
get { return m_iVal; }
set { m_iVal = value; }
}
A m_objA;
public A AObject {
get { return m_objA; }
set { m_objA = value; }
}
}
Now, I need to identify the classes of the objects passed to a function
void MyFunc(object obj) {
Type type = obj.GetType();
foreach (PropertyInfo pi in type.GetProperties()) {
if (pi.PropertyType.IsClass) { //I need objects only
if (!type.IsGenericType && type.FullName.ToLower() == "system.string") {
object _obj = pi.GetValue(obj, null);
//do something
}
}
}
}
I don't like this piece of code -
if (!type.IsGenericType && type.FullName.ToLower() == "system.string") {
because then i have to filter out classes like, System.Int16, System.Int32, System.Boolean and so on.
Is there an elegant way through which I can find out if the object is of a class defined by me and not of system provided basic classes?
One possible approach would be to use the Type.Assembly property and filter out anything that is not declared in one of your assemblies. The drawback of this approach is that you need to know all your assemblies at execution time, which might be hard in certain (not as common) scenarios.
There isn't really a reliable way. One thing that comes to mind is to look at the assembly the given type is defined: type.Assembly and compare this against a list of known assemblies.
As far as I Know there is no way to know if a class is from the BCL or is a user defined class but maybe you could just cache some assembly information from some well known framework dll.
You could cycle through all the classes in mscorlib.dll and put them into a List and then checking your class names against that list.
You could have a look at the PublicKeyToken attribute of the AssemblyQualifiedName on the type's Assembly property. But you would have to gather up the different tokens used by the framework for different versions of the runtime and compare to those.
The easiest way, if you have the possibility, is to mark your own classes with an attribute that you can check for (instead of checking for generics and the name of the type).
I've got a cheap and quick solution that might work:
if( type.IsClass && ! type.IsSealed )
The System.String object is a class but it is also sealed against inheritance. This works as long as you aren't using sealed classes in your code.

Categories