By John Frankewicz - 11/29/2005
Our application requires that fields in the database, represented by the business object, be serialized remotely.Could someone explain the process or point me to a link that explains how this process is done in your framework? 1. Do you have an option where the serialized data is stored? 2. Can it be hooked into the .net remoting? 3. How do you select what is serialized? I thought it was done after the object is dropped on the form?
|
By Trent L. Taylor - 11/29/2005
There are two serialization methods on a business object: SerializeToStream and SerialzieToByteArray. These work just as the names state. SerializeToStream supports any stream type such as a network stream, file stream, memory stream, etc. Here is a sample of serializing a business object and then de-serializing it. I am using a file stream here for sample purposes, but you could just as easily use a network stream which could be remoted or allow you to create a server that hands out business objects. The possibilities are limitless.
Serialize the Business Object
Private Sub SerializeMethod()
'-- Establish Locals
Dim loFile As New System.IO.FileStream("c:\serializedBO.bin", System.IO.FileMode.Create)
Dim loCustomers As New CustomersBO()
'-- Load some data into the business object
loCustomers.FillAll()
'-- Serialize the business object to the stream
loCustomers.SerializeToStream(loFile)
'-- Close the stream
loFile.Close()
'-- Close the BO
loCustomers.Dispose()
End Sub
De-serialize the Business Object
Private Sub DeserializeMethod()
'-- Establish Lcoals
Dim loFile As New System.IO.FileStream("c:\serializedBO.bin", System.IO.FileMode.Open)
Dim loCustomers As CustomersBO
'-- Deserialize the saved business object from a stream
loCustomers = CustomersBO.DeserializeBusinessObject(loFile)
'-- Close the stream
loFile.Close()
End Sub
|
By Edhy Rijo - 3/11/2009
Hi Trent,I am trying to use the BO.SerializeToStream and DeserializeBusinessObject based on the error in the previous post, but I am hitting an error. Here is the version of the code I am using: Private Sub SerializeMethod() '-- Establish Locals Dim memString As New System.IO.MemoryStream Dim loCustomers As New CustomersBO() '-- Load some data into the business object loCustomers.FillAll() '-- Serialize the business object to the stream loCustomers.SerializeToStream(memString) '-- Close the stream memString.Close() '-- Close the BO loCustomers.Dispose() Me.DeserializeMethod(memString)End Sub'De-serialize the Business ObjectPrivate Sub DeserializeMethod(ByVal memString As System.IO.MemoryStream) '-- Establish Lcoals Dim loCustomers1 As New CustomersBO '-- Deserialize the saved business object from a stream loCustomers1 = CustomersBO.DeserializeBusinessObject(memString) End Sub Here is the stack error: ArgumentException Stream was not readable. Source : mscorlib Stack Trace: at System.IO.BinaryReader..ctor(Stream input, Encoding encoding) at System.Runtime.Serialization.Formatters.Binary.__BinaryParser..ctor(Stream stream, ObjectReader objectReader) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, Boolean isCrossAppDomain, IMethodCallMessage methodCallMessage) at System.Runtime.Serialization.Formatters.Binary.BinaryFormatter.Deserialize(Stream serializationStream, HeaderHandler handler, Boolean fCheck, IMethodCallMessage methodCallMessage) at MicroFour.StrataFrame.Business.BusinessLayer.DeserializeBusinessObject(Stream InputStream) at CollisionTest.testForm.DeserializeMethod(MemoryStream memString) in E:\Visual Studio 2008 Projects\StrataFrame\Samples\AutoCompleteTest\AutoCompleteTest\TestForm.vb:line 41 at CollisionTest.testForm.SerializeMethod() in E:\Visual Studio 2008 Projects\StrataFrame\Samples\AutoCompleteTest\AutoCompleteTest\TestForm.vb:line 31 at CollisionTest.testForm.Button1_Click(Object sender, EventArgs e) in E:\Visual Studio 2008 Projects\StrataFrame\Samples\AutoCompleteTest\AutoCompleteTest\TestForm.vb:line 11 at System.Windows.Forms.Control.OnClick(EventArgs e) at System.Windows.Forms.Button.OnMouseUp(MouseEventArgs mevent) at System.Windows.Forms.Control.WmMouseUp(Message& m, MouseButtons button, Int32 clicks) at System.Windows.Forms.Control.WndProc(Message& m) at System.Windows.Forms.ButtonBase.WndProc(Message& m) at System.Windows.Forms.Button.WndProc(Message& m) at System.Windows.Forms.Control.ControlNativewindow.WndProc(Message& m) at System.Windows.Forms.Nativewindow.Callback(IntPtr hWnd, Int32 msg, IntPtr wparam, IntPtr lparam)
Testing with System.IO.FileStream works just fine, what do I need to make it work with a System.IO.MemoryStream?
|
By Edhy Rijo - 3/11/2009
Edhy Rijo (03/11/2009) I am trying to use the BO.SerializeToStream and DeserializeBusinessObject based on the error in the previous post, but I am hitting an error. Here is the version of the code I am using:Sorry, the highlighted phrase should have said: based on the code...
|
By Trent L. Taylor - 3/12/2009
You are welcome to post a sample reproducing the error, because I just tested this and it works fine. So there must be something else going on within your environment. I just did this and it worked:Dim mem As New System.IO.MemoryStream() Me.CustomerBO1.SerializeToStream(mem)
|
By Edhy Rijo - 3/12/2009
Hi Trent,The problem is with DeserializeBusinessObject. In your test did you try loCustomers1 = CustomersBO.DeserializeBusinessObject(memString) 'De-serialize the Business Object Private Sub DeserializeMethod(ByVal memString As System.IO.MemoryStream) '-- Establish Lcoals Dim loCustomers1 As New CustomersBO '-- Deserialize the saved business object from a stream loCustomers1 = CustomersBO.DeserializeBusinessObject(memString) End Sub
I can not post a sample right now because I am not in the office, but I would appreciate if you can try deserializing the memory stream. Thanks!
|
By Trent L. Taylor - 3/12/2009
Yup, it worked. You have to reposition the stream back to the 0 position, but it works like it should.Dim mem As New System.IO.MemoryStream() Me.CustomerBO1.SerializeToStream(mem) mem.Seek(0, IO.SeekOrigin.Begin) Dim desObj As CustomerBO = MicroFour.StrataFrame.Business.BusinessLayer.DeserializeBusinessObject(mem)
|
By Edhy Rijo - 3/12/2009
Trent L. Taylor (03/12/2009) Yup, it worked. You have to reposition the stream back to the 0 position, but it works like it should. Trent, thanks a lot for testing this, the missing part was the code to reposition the stream back to the 0 position. Dim mem As New System.IO.MemoryStream() Me.CustomerBO1.SerializeToStream(mem) mem.Seek(0, IO.SeekOrigin.Begin) Dim desObj As CustomerBO = MicroFour.StrataFrame.Business.BusinessLayer.DeserializeBusinessObject(mem)
Since this my first time working with a MemoryStream, I wonder, should the BO.DeserializeBusinessObject(mem) method take care of repositioning the passed stream to the 0 position?
|
By Trent L. Taylor - 3/12/2009
Since this my first time working with a MemoryStream, I wonder, should the BO.DeserializeBusinessObject(mem) method take care of repositioning the passed stream to the 0 position? No. This could cause all types of issues. This is the responsibility of the developer. The same issue would come up with a file. Most of the time you are not trying to do all of this within the same segment of code, the difference here is that you wrote to it then turned right around and read from it...so in this instance you have to reset the pointer.
|
By Edhy Rijo - 3/13/2009
Trent, Another question about serialization, when we use this command: pszOutMemByte = Me.bizConnectedClients1.SerializeToByteArray()
Is there a way to add some extra data to the pszOutMemByte variable? With my communication library, I need to add and End Of Line character to the byte stream and have not found a way to do this, so the communication event will trigger when all data have arrive, so the question is how do I add these character to this byte array pszOutMemByte?
|
By Trent L. Taylor - 3/14/2009
Sure. If I were going to do this I would put it in the front of the byte array with any information that will tell me where the serialized BO starts, etc. So the beginning of the byte array would be a "header" that contained whatever information that you needed. This is why I mentioned that resetting the memory stream was not a safe thing to do as other people may be using the memory stream for other things.
|
By Edhy Rijo - 3/14/2009
Trent L. Taylor (03/14/2009) Sure. If I were going to do this I would put it in the front of the byte array with any information that will tell me where the serialized BO starts, etc. So the beginning of the byte array would be a "header" that contained whatever information that you needed. This is why I mentioned that resetting the memory stream was not a safe thing to do as other people may be using the memory stream for other things.
Yes, but can you give me a sample code of how to add the info to the byte array? in my case I will enter the code at the end of the array and the communication library will take care of removing it from the transferred stream.
|
By Trent L. Taylor - 3/15/2009
Hmmm....it is going to be a lot mroe difficult to add it at the end as you will not know the length of the serialized BO. That is why a header would work much better as you would know what to expect that tells you what is further down the stream.
|
By Edhy Rijo - 3/15/2009
Trent L. Taylor (03/15/2009) Hmmm....it is going to be a lot mroe difficult to add it at the end as you will not know the length of the serialized BO. That is why a header would work much better as you would know what to expect that tells you what is further down the stream.Hi again, Thanks, but could you provide a quick sample code on how to add this byte to the header? sorry, but I am really lost here
|
By Trent L. Taylor - 3/16/2009
Well, it would just be a matter of creating your header in a string format, etc. Then place that header at the beginning. For example, I might have an enum that tells me the contents of the byte array in the first element. In this case, a "1" would indicate a business object. You could make this as long as you need since you would be in control of the header. The second part of the header may indicate, in bytes, the length of the serialized BO.Dim header As String = "1|" Dim bo() As Byte Dim mem As New System.IO.MemoryStream() Dim headerInBytes() As Byte '-- Serialize the BO to a byte array bo = MyBO.SerializeToByteArray() '-- Create the header header &= bo.Length.ToString() '-- Place an ending tag on the header header &= "|" headerInBytes = System.Text.ASCIIEncoding.ASCII.GetBytes(header) '-- Create the full byte array mem.Write(headerInBytes, 0, headerinBytes.Length) '-- Add the BO to the byte array mem.Write(bo, 0, bo.Length) '-- Convert the stream into a byte array mem.Seek(0, Begin) Dim r() As Byte = mem.ToArray() So when you get the byte array on the server side (or whereever) you already know what to expect in the header. So you can parse it out of the array (convert it back into a string or whatever you expect) and then you know what to do with the rest of the array.
|
By Edhy Rijo - 3/16/2009
Thanks a lot Trent, that will get me started.
|