serialize objects to transfer into the messagequeue instance - c#

I was going through the msdn post of system.messaging namespace and come across a doubt about object serialization. I want to know that is it always important to that object must be xmlserializable in order to be transferred over a MessageQueue instance.
Second, if we are invoking the MessageQueue.Send member is this also means that we are using default System.Messaging.XmlMessageFormatter.
An explanation would be appreciative.
Thanks

you don't have to use xml, you can use BinaryMessage like this
BinaryMessageFormatter formatter = new BinaryMessageFormatter();
System.Messaging.Message message = new System.Messaging.Message(YourObject, formatter);
second, xml message is the default, although I have always used binary, xml is to bulky for almost all kind of scenarios.

Related

Loosing an XML file when using XmlSerializer

Sometimes, when I save to XML, I end up with a completely empty XML file.
I can't reproduce the issue on demand yet. It is just occasional. Are there steps that one can take to assist the user in this regard?
At the moment I do this:
public bool SavePublisherData()
{
bool bSaved = false;
try
{
XmlSerializer x = new XmlSerializer(_PublisherData.GetType());
using (StreamWriter writer = new StreamWriter(_strPathXML))
{
_PublisherData.BuildPublisherListFromDictionary();
x.Serialize(writer, _PublisherData);
bSaved = true;
}
}
catch
{
}
return bSaved;
}
The reason I have not put anything in the catch block is because this code is part of a C# DLL and I am calling it from an MFC project. I have read that you can't (or shouldn't) pass exceptions through from one environment to another. Thus, when an exception happens in my DLL I don't really know how I can sensibly feed that information to the user so they can see it. That is a side issue.
But this is how I save it. So, what steps can one take to try and prevent complete data loss?
Thank you.
Update
I have looked at the KB article that the link in the comments refers to and it states:
Use the following XmlSerializer class constructors. These class constructors cache the assemblies.
This is also re-stated in the article itself indicated in the comments:
What is the solution?
The default constructors XmlSerializer(type) and XmlSerializer(type, defaultNameSpace) caches the dynamic assembly so if you use those constructors only one copy of the dynamic assembly needs to be created.
Seems pretty smart… why not do this in all constructors? Hmm… interesting idea, wonder why they didn’t think of that one:) Ok, the other constructors are used for special cases, and the assumption would be that you wouldn’t create a ton of the same XmlSerializers using those special cases, which would mean that we would cache a lot of items we later didn’t need and use up a lot of extra space. Sometimes you have to do what is good for the majority of the people.
So what do you do if you need to use one of the other constructors? My suggestion would be to cache the XmlSerializer if you need to use it often. Then it would only be created once.
My code uses one of these default constructors as you can see:
XmlSerializer(_PublisherData.GetType());
So I don't think I need to worry about this XmlSerializerFactory in this instance.

Message Queues with different message types

I'm investigating Microsoft Message Queues for doing inter-process cross-network messaging. But when I receive a message, I don't know a priori what type of object I'm getting, so the code
queue.Formatter = new XmlMessageFormatter(new Type[] { typeof(Wibble) });
can't be applied before I get the message because I don't know if it's a Wibble. So how do I receive different message types?
You're already using the constructor overload for XmlMessageFormatter that accepts an array of types. So just add all of the types that you're expecting to receive into that array, rather than just one type.
queue.Formatter = new XmlMessageFormatter(new Type[] {
typeof(Wibble),
typeof(Fleem),
typeof(Boo)
});
From TargetTypes:
The instance serialized in the message body must comply with one of the schemas represented in the type array. When you read the message using the Receive method, the method creates an object of the type that corresponds to the schema identified and reads the message body into it.
(Emphasis added)
You might consider not storing your object in the MSMQ message, but instead putting a reference to it's persistent location if you can. MSMQ has finite space on the message queues, so smaller messages are best.
If you can't do that, you can serialize your object to the messages BodyStream directly, using whatever serializer you like. Then store the type name as well, probably best in the message Label.
Something very similar to this (scratched it out here, no IDE on this computer) to put it in, and the analagous action on the way out:
public void FormatObject(object toFormat, Message message)
{
var serializer = new XmlSerializer(toFormat.GetType());
var stream = new MemoryStream();
serializer.Serialize(toFormat, stream);
//don't dispose the stream
message.BodyStream = stream;
message.Label = toFormat.GetType().AssemblyQualifiedName;
}
There is a great amount of misinformation running around on MSMQ primarily because the Microsoft documentation is frighteningly sparse on how to design a message send receive properly. I have both of the MSMQ books published on this subject and I'm still searching for sensible designs on the internet.
So, neither of these references say that there is a one message type to a queue requirement. And that would make PeakMessage and variants unnecessary and even stupid. Microsoft is vague and difficult in its documentation, but I've worked there and they are never stupid.
There is a constant irritating suggestion to use a CLSID as an identifier, a practice that is annoyingly short sighted. How about trying to embed the message type in the LABEL??? Then use PeadMessage to run up the Queue until you find a message meant expressly for your particular queue and with a message type that you can use to format the message properties to receive the message properly on the first try???
I know this makes for a complex code set, but would you rather do without? Or would you actually try to implement the suggestion of the responder above who is implying that if you have a system of 200 users with 200 message types that they should create 80,000 queues to manage all the one to one requirements? Some people just don't think these things through.
As joocer notes in a comment: use a different queue for different message types.
Alternatively you could agree with the message senders that all messages will be XML (anything that doesn't parse as XML is rejected). Then also agree to some basics of the XML schema: a header element with a message type (and version).
Then process (either yourself of via a serialiser) into the internal type.
Of course in many cases – where there is no real benefit to a deserialisation – just read the content of the XML as required.

How does BinaryFormatter.Deserialize create new objects?

When BinaryFormatter deserializes a stream into objects, it appears to create new objects without calling constructors.
How is it doing this? And why? Is there anything else in .NET that does this?
Here's a demo:
[Serializable]
public class Car
{
public static int constructionCount = 0;
public Car()
{
constructionCount++;
}
}
public class Test
{
public static void Main(string[] args)
{
// Construct a car
Car car1 = new Car();
// Serialize and then deserialize to create a second, identical car
MemoryStream stream = new MemoryStream();
BinaryFormatter formatter = new BinaryFormatter();
formatter.Serialize(stream, car1);
stream.Seek(0, SeekOrigin.Begin);
Car car2 = (Car)formatter.Deserialize(stream);
// Wait, what happened?
Console.WriteLine("Cars constructed: " + Car.constructionCount);
if (car2 != null && car2 != car1)
{
Console.WriteLine("But there are actually two.");
}
}
}
Output:
Cars constructed: 1
But there are actually two.
There are two things calling a constructor does (or at least should do).
One is to set aside a certain amount of memory for the object and does all the housekeeping necessary for it to be an object to the rest of the .NET world (note certain amount of handwaving in this explanation).
The other is to put the object into a valid initial state, perhaps based on parameters - this is what the actual code in the constructor will do.
Deserialisation does much the same thing as the first step by calling FormatterServices.GetUninitializedObject, and then does much the same thing as the second step by setting the values for fields to be equivalent to those that were recorded during serialisation (which may require deserialising other objects to be said values).
Now, the state that deserialisation is putting the object into may not correspond to that possible by any constructor. At best it will be wasteful (all values set by the constructor will be overwritten) and at worse it could be dangerous (constructor has some side-effect). It could also just be impossible (only constructor is one that takes parameters - serialisation has no way of knowing what arguments to use).
You could look at it as a special sort of constructor only used by deserialisation (OO purists will - and should - shudder at the idea of a constructor that doesn't construct, I mean this as an analogy only, if you know C++ think of the way overriding new works as far as memory goes and you've an even better analogy, though still just an analogy).
Now, this can be a problem in some cases - maybe we have readonly fields that can only be set by a constructor, or maybe we have side-effects that we want to happen.
A solution to both is to override serialisation behaviour with ISerializable. This will serialise based on a call to ISerializable.GetObjectData and then call a particular constructor with SerializationInfo and StreamingContext fields to deserialise (said constructor can even be private - meaning most other code won't even see it). Hence if we can deserialise readonly fields and have any side-effects we want (we can also do all manner of things to control just what is serialised and how).
If we just care about ensuring some side-effect happens on deserialisation that would happen on construction, we can implement IDeserializationCallback and we will have IDeserializationCallback.OnDeserialization called when deserialisation is complete.
As for other things that do the same thing as this, there are other forms of serialisation in .NET but that's all I know of. It is possible to call FormatterServices.GetUninitializedObject yourself but barring a case where you have a strong guarantee that subsequent code will put the object produced into a valid state (i.e. precisely the sort of situation you are in when deserialising an object from data produced by serialising the same sort of object) doing such is fraught and a good way to produce a really hard to diagnose bug.
The thing is, BinaryFormatter isn't really making your particular object. It's putting an object graph back into memory. The object graph is basically the representation of your object in memory; this was created when the object is serialized. Then, the deserialize call basically just sticks that graph back in memory as an object at an open pointer, and then it gets casted to what it actually is by the code. If it's casted wrong, then an exception is thrown.
As to your particular example, you are only really constructing one car; you are just making an exact duplicate of that car. When you serialize it off into the stream, you store an exact binary copy of it. When you deserialize it, you don't have to construct anything. It just sticks the graph in memory at some pointer value as an object and lets you do whatever you want with it.
Your comparison of car1 != car2 is true because of that different pointer location, since Car is a reference type.
Why? Frankly, it's easy to just go pull the binary representation, rather than having to go and pull each property and all that.
I'm not sure whether anything else in .NET uses this same procedure; the most likely candidates would be anything else that uses an object's binary in some format during serialization.
Not sure why the constructor does not get called but I use IDeserializationCallback as a work around.
also take a look at
OnSerializingAttribute
OnSerializedAttribute
OnDeserializingAttribute
OnDeserializedAttribute

I have a Single File And need to serialize multiple objects randomly. How can I in c#?

I have a single file and need to serialize multiple objects of the same class when ever a new object is created. I can't store them in arrays as I need to serialize them the instance an object is create. Please, help me.
What serialization mechanism are you using? XmlSerializer might be a problem because of the root node and things like namespace declarations, which are a bit tricky to get shot of - plus it isn't great at partial deserializations. BinaryFormatter is very brittle to begin with - I don't recommend it in most cases.
One option might be protobuf-net; this is a binary serializer (using Google's "protocol buffers" format - efficient, portable, and version-tolerant). You can serialize multiple objects to a stream with Serializer.SerializeWithLengthPrefix. To deserialize the same items, Serializer.DeserializeItems returns an IEnumerable<T> of the deserialized items - or you could easily make TryDeserializeWithLengthPrefix public (it is currently private, but the source is available).
Just write each object to file after you have created it - job done.
If you want an example, please say - although the unit tests here give an overview.
It would basically be something like (untested):
using(Stream s = File.Create(path))
{
Serializer.SerializeWithLengthPrefix(s, command1, PrefixStyle.Base128, 0);
... your code etc
Serializer.SerializeWithLengthPrefix(s, commandN, PrefixStyle.Base128, 0);
}
...
using(Stream s = File.OpenRead(path)) {
foreach(Command command in
Serializer.DeserializeItems<Command>(s, PrefixStyle.Base128, 0))
{
... do something with command
}
}
See answer here.
In short, just serialize everything to the same file stream, and then deserialize. dotNet would know the size of each object
For every object that arrives, we will convert it into a Base64Encoded string and store it as one line in a text file. So, in this file, every row will have a serialized object per line. While reading we will read the file one line at a time and deserialize this Base64 encoded string into our Object. Easy.. so lets try out the code.
http://www.codeproject.com/KB/cs/serializedeserialize.aspx?display=Print

Should I use exceptions in C# to enforce base class compatibility?

On one hand, I'm told that exceptions in C# are 'expensive', but on the other, I'm stuck on how to implement this.
My problem is this: I'm making a Stream derivitive, that wraps a NetworkStream. Now, the problem I'm facing is this: Read(byte[] buffer, int offset, int count). From the Stream docs for the function:
Returns:
... or zero (0) if the end of the stream has been reached.
The problem is, in the protocol I'm implementing the remote side can send an "end of record" token, or a "please respond" token. Obviously, if this happens at the start of the Read() this causes problems, since I need to return from the function, and I havn't read anything, so I need to return 0, which means the stream is finished, but it isn't... is a EndOfRecordException or similar justified in this case? And in this case, should it aways be thrown when this token is encountered (at the start of the Read() call and make sure these tokens are always at the start by returning early) so that there is some sort of pattern to how these tokens should be handled.
Edit: For what it's worth, these tokens generally come through 3-10 times a second. At the most, I wouldn't expect more than 25 a second.
Exceptions aren't really all that expensive - but they also aren't necessarily the best way to manage expected/normal flow.
To me, it sounds like you aren't actually implementing a Stream - you are encapsulating a stream into a "reader". I might be inclined to write a protocol-specific reader class with suitable methods to detect the end of a record, or Try... methods to get data or return false.
It sounds like you shouldn't really be deriving from Stream if your class is concerned with records. Streams don't generally interpret their data at all - they're just a transport mechanism of data from one place to another.
There have been cases like ZipInputStream in Java which end up being very confusing when a single InputStream effectively has several streams within it, and you can skip between them. Such APIs have been awful to use in my experience. Providing a separate class to implement the "record splitting" which can provide a stream for the data within a record sounds cleaner to me. Then each stream can behave consistently with normal streams. No need for new exceptions.
However, I'm just guessing at your context based on the limited information available. If you could give more details of the bigger picture, that would help.
It's not such a big deal performance-wise, but still... Exceptions are intended for, well, exceptions. Situations that are "unusual". If that is the way the underlying stream behaves, then your stream should be able to handle it. If it can, it should handle it on its own. If not, you can have the user set some callback or something which will get called when you receive a "please respond" token.
I believe that Stream-derived class should deal only with streaming issues and adhere to Stream semantic contract. All higher-level logic (interpreting EOF and EOR tokens) should be placed in some other class.
Maybe you can create an enum that you return, this enum can contain items for EndOfRecord, EndOfStream, ReadOk or whatever you need.
The actual read data can be passed as an out parameter.

Categories