Serializing an Array - Unknown type for Value object

Aug 11, 2009 at 8:49 PM

I have the event system up and running and can pass basic data types like int and simple objects like GUID. However, what I really need to send is an array of floats.  When I attempt to do so I get an exception "Unknown type for Value object". This error leads me to believe that you can only send objects that are or contain value types (int, float) and not reference types like an array. Is this correct? Any sugestions on how to proceed (do I have to write my own serialization routine)?

Thanks, Michael

Coordinator
Aug 12, 2009 at 12:21 AM
mhannan wrote:

I have the event system up and running and can pass basic data types like int and simple objects like GUID. However, what I really need to send is an array of floats.  When I attempt to do so I get an exception "Unknown type for Value object". This error leads me to believe that you can only send objects that are or contain value types (int, float) and not reference types like an array. Is this correct? Any sugestions on how to proceed (do I have to write my own serialization routine)?

Thanks, Michael

 Tomorrow I'll upload the latest version of the code. I will then show you how to serialize/deserialize your array. If you send me your class, I'll just put the code in it.

Aug 12, 2009 at 1:32 PM

Kieth,

Thanks for the quick reply. I am pretty new at .NET and it may just be ignorance that is the problem. I really appriceate you taking the time to help out.

Here is the simple event I was trying to make.

    /// <summary>
    /// Implmentaion of WSP Event class.
    /// Do properties need both a get and set for the serialization to properly work?
    /// </summary>
    public class Lidar2dDataWspEvent : Event
    {
        /// <summary>
        /// This is user supplied Data. This property is for keeping track of the number events that have been fired.
        /// </summary>
        public UInt64 EventNum
        {
            get { return m_eventNum; }
            set { m_eventNum = value; }
        }
        UInt64 m_eventNum;

        /// <summary>
        /// This is user supplied Data. Set this property right after you create the event.
        /// It is useful when there are multiple publishers of the same event.
        /// </summary>
        public Guid InstanceId
        {
            get { return m_instanceId; }
            set { m_instanceId = value; }
        }
        Guid m_instanceId;

        /// <summary>
        /// X in rectanglular points
        /// </summary>
        public float[] X
        {
            get { return (float[])m_X.Clone(); }
            set { m_X = (float[])value.Clone(); }
        }
        float[] m_X;

        /// <summary>
        /// Y in rectanglular points
        /// </summary>
        public float[] Y
        {
            get { return (float[])m_Y.Clone(); }
            set { m_Y = (float[])value.Clone(); }
        }
        float[] m_Y;



        /// <summary>
        /// Base constructor that will be used by the Publisher to to create a new event. 
        /// </summary>
        public Lidar2dDataWspEvent()
            : base()
        {
            EventType = new Guid(@"24923A0F-04CB-4dcb-8EA9-3D1CAA316B23");
            EventName = "Lidar2dData";
        }

        /// <summary>
        /// Base constructor that will be used by the Subscriber to create a local 
        /// copy of the event from the supplied serialized event 
        /// </summary>
        /// <param name="serializationData">Serialized event data</param>
        public Lidar2dDataWspEvent(byte[] serializationData)
            : base(serializationData)
        {
        }


        /// <summary>
        /// Used for event serialization. Called when an event is published.
        /// </summary>
        /// <param name="data">SerializationData object passed to store serialized object</param>
        public override void GetObjectData(SerializationData data)
        {
            // add user data to event
            data.AddElement(@"EventNum", EventNum);
            data.AddElement(@"InstanceId", InstanceId);
            data.AddElement(@"X", X);
            data.AddElement(@"Y", Y);
        }
    }

 

Coordinator
Aug 13, 2009 at 2:14 AM
Below is your class with the logic to serialize/deserialize the arrays.
    /// <summary>
    /// Implmentaion of WSP Event class.
    /// Do properties need both a get and set for the serialization to properly work?
    /// </summary>
    public class Lidar2dDataWspEvent : Event
    {
        /// <summary>
        /// This is user supplied Data. This property is for keeping track of the number events that have been fired.
        /// </summary>
        public UInt64 EventNum
        {
            get { return m_eventNum; }
            set { m_eventNum = value; }
        }
        UInt64 m_eventNum;

        /// <summary>
        /// This is user supplied Data. Set this property right after you create the event.
        /// It is useful when there are multiple publishers of the same event.
        /// </summary>
        public Guid InstanceId
        {
            get { return m_instanceId; }
            set { m_instanceId = value; }
        }
        Guid m_instanceId;

        /// <summary>
        /// X in rectanglular points
        /// </summary>
        public float[] X
        {
            get { return (float[])m_X.Clone(); }
            set { m_X = (float[])value.Clone(); }
        }
        float[] m_X;

        /// <summary>
        /// Y in rectanglular points
        /// </summary>
        public float[] Y
        {
            get { return (float[])m_Y.Clone(); }
            set { m_Y = (float[])value.Clone(); }
        }
        float[] m_Y;



        /// <summary>
        /// Base constructor that will be used by the Publisher to to create a new event. 
        /// </summary>
        public Lidar2dDataWspEvent()
            : base()
        {
            EventType = new Guid(@"24923A0F-04CB-4dcb-8EA9-3D1CAA316B23");
            EventName = "Lidar2dData";
        }

        /// <summary>
        /// Base constructor that will be used by the Subscriber to create a local 
        /// copy of the event from the supplied serialized event 
        /// </summary>
        /// <param name="serializationData">Serialized event buffer</param>
        public Lidar2dDataWspEvent(byte[] serializationData)
            : base(serializationData)
        {
        }

        /// <summary>
        /// Used for event serialization. Called when an event is published.
        /// </summary>
        /// <param name="buffer">SerializationData object passed to store serialized object</param>
        public override void GetObjectData(WspBuffer buffer)
        {
            // add user buffer to event
            buffer.AddElement(@"EventNum", EventNum);
            buffer.AddElement(@"InstanceId", InstanceId);

            buffer.AddElement(@"X", m_X.Length);
            for (int i = 0; i < m_X.Length; i++)
            {
                buffer.Write(m_X[i]);
            }

            buffer.AddElement(@"Y", m_Y.Length);
            for (int i = 0; i < m_Y.Length; i++)
            {
                buffer.Write(m_Y[i]);
            }
        }

        /// <summary>
        /// Set values on object during deserialization
        /// </summary>
        /// <param name="elementName">Name of property</param>
        /// <param name="elementValue">Value of property</param>
        /// <returns></returns>
        public override bool SetElement(string elementName, object elementValue)
        {
            switch (elementName)
            {
                case "EventNum":
                    EventNum = (UInt64)elementValue;
                    break;

                case "InstanceId":
                    InstanceId = (Guid)elementValue;
                    break;

                case "X":
                    int xLength = (int)elementValue;
                    m_X = new float[xLength];
                    for (int i = 0; i < m_X.Length; i++)
                    {
                        float floatValue;
                        this.SerializedEvent.Read(out floatValue);
                        m_X[i] = floatValue;
                    }
                   break;

                case "Y":
                   int yLength = (int)elementValue;
                   m_Y = new float[yLength];
                   for (int i = 0; i < m_Y.Length; i++)
                   {
                       float floatValue;
                       this.SerializedEvent.Read(out floatValue);
                       m_Y[i] = floatValue;
                   }
                   break;

                default:
                    base.SetElement(elementName, elementValue);
                    break;
            }

            return true;
        }
    }

Aug 13, 2009 at 3:28 PM

Thank you

Aug 14, 2009 at 3:17 AM

There seems to be a problem with the latest version of code that you uploaded. When I try to run the examples I keep getting the same error (does not matter if it is debug or release version). Note, the examples come with references to Base and PubSubMgr, but they do not exist in the install.

The example code fails with an exception at the following call.

pubMgr = new PublishManager();

Microsoft.WebSolutionsPlatform.Event.PubSubManager.PubSubQueueDoesNotExistException was unhandled
  Message="Queue name does not exist"
  Source="WspPubSubMgr"
  StackTrace:
       at Microsoft.WebSolutionsPlatform.Event.PubSubManager.PublishManager..ctor(UInt32 timeout)
       at Microsoft.WebSolutionsPlatform.Event.PubSubManager.PublishManager..ctor()
       at Microsoft.Sample.EventPingPong.Form1..ctor() in C:\Program Files\Microsoft\WspEventRouter\Samples\EventPingPong\Form1.cs:line 36
       at Microsoft.Sample.EventPingPong.Program.Main() in C:\Program Files\Microsoft\WspEventRouter\Samples\EventPingPong\Program.cs:line 20
       at System.AppDomain._nExecuteAssembly(Assembly assembly, String[] args)
       at System.AppDomain.ExecuteAssembly(String assemblyFile, Evidence assemblySecurity, String[] args)
       at Microsoft.VisualStudio.HostingProcess.HostProc.RunUsersAssembly()
       at System.Threading.ThreadHelper.ThreadStart_Context(Object state)
       at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
       at System.Threading.ThreadHelper.ThreadStart()
  InnerException:

Coordinator
Aug 14, 2009 at 4:48 AM

Did you start the Wsp Event System service?

Aug 15, 2009 at 6:23 PM

Yeah, novice mistake.  The difference was that in the previous version the serivce started automatically after I installed it.  However, the new release did not start automatically. When I went into the Windows component service application that service was listed as automatic, but it was not started. One I started it, every things was up and working.