public void WorkspaceDataConstructorTest() { object data = new TraceLab.Core.Test.Workspaces.TestObject(); WorkspaceUnitData target = new WorkspaceUnitData(data); Assert.AreEqual(data, target.Data); }
/// <summary> /// WorkspaceWrapper load ensures using mapping. /// It also checks if component had declared Input of the given unitname, and the same type. If this is not the case, method throws exception. /// /// Load is implemented so the deserialization from byte array to the workspace unit data is done locally in the wrapper and not in the Workspace itself. /// /// Thanks to this implementation deserialization happens only once per each Load. /// Previously during Load, object was deserialized in Workspace from cache stream into object, then the object was serialized and deserialized while crossing app domain border. /// </summary> /// <param name="unitname">The name of the variable to be loaded. Notice this is not a mapping value, mapping comes from IOSpec. Unitname had to be declared by the component in definition.</param> /// <returns></returns> public Object Load(string unitname) { string mapping; if (IOSpec.TryGetInputMapping(unitname, out mapping) == false) { throw new WorkspaceException(String.Format(CultureInfo.CurrentCulture, "Component has not declared any input of the given name '{0}'", unitname)); } if (String.IsNullOrEmpty(mapping)) { throw new WorkspaceException(String.Format(CultureInfo.CurrentCulture, "'Mapped to' cannot be empty. Please provide the value for the mapping.")); } //return m_workspace.Load(mapping); // not used due to low performance when returning object was crossing app domain boundary var bytes = LoadBytes(mapping); Object data; if (bytes == null) { //it means that workspace didn't have specific object data, so there is nothing to deserialize //simply return null data = null; } else { WorkspaceUnitData workspaceUnitData = null; //otherwise deserialize given bytes using (var dataStream = new MemoryStream(bytes)) { var reader = new BinaryReader(dataStream); try { workspaceUnitData = (WorkspaceUnitData)Activator.CreateInstance(typeof(WorkspaceUnitData), true); workspaceUnitData.ReadData(reader); } catch { // If deserialization failed, the cache is // corrupt or invalid - attempt to delete and clear the cache Delete(mapping); workspaceUnitData = null; } } if (workspaceUnitData == null) { throw new WorkspaceException(String.Format("Loading {0} data failed.", mapping)); } data = workspaceUnitData.Data; } return data; }
/// <summary> /// WorkspaceWrapper store method ensures using the Outpus As parameter, instead of output name directly. /// It also checks if component had declared Output of the given unitname, and checks if the provided object type matches the type declared in IOSpec. /// /// Store id implemented so that the serialization of the object to stream and then array /// happen locally in the wrapper and not in the Workspace itself. /// /// Thanks to this implementation serialization happens only once per each Store. /// Previously during Store object was serialized and deserialized when crossing app domain border, and then serialized into the cache stream in Workspace. /// </summary> /// <param name="unitname">The name of the variable to be stored. Notice this is going to be stored with a name specified in IOSpec by 'Output As' parameter. Unitname had to be declared by the component in definition.</param> /// <param name="unit">Type of the variable. It has to match the type declared in the definition.</param> public void Store(string unitname, object unit) { if (unit == null) { throw new WorkspaceException(String.Format(CultureInfo.CurrentCulture, "Given object is null. It is not allowed to store null objects in the workspace.", unitname)); } string mapping; if (IOSpec.TryGetOutputMapping(unitname, out mapping) == false) { throw new WorkspaceException(String.Format(CultureInfo.CurrentCulture, "Component has not declared any output of the given name '{0}'", unitname)); } if ((mapping != null && mapping.Length == 0)) { throw new WorkspaceException(String.Format(CultureInfo.CurrentCulture, "'Output as' or 'Input as' cannot be empty. Please provide the name value for the parameter.")); } if (mapping.Contains(Workspace.NAMESPACE_DELIMITER)) { throw new WorkspaceException(String.Format("Output mapping '{0}' cannot contain character '{1}'", mapping, Workspace.NAMESPACE_DELIMITER)); } //m_workspace.Store(mapping, unit); // not used anymore because of low performance when stored object was crossing app domain boundary try { // wrap unit into workspace data and serializae it to the stream WorkspaceUnitData workspaceData = new WorkspaceUnitData(unit); MemoryStream stream = new MemoryStream(); BinaryWriter writer = new BinaryWriter(stream); //BinaryFormatter bf = new BinaryFormatter(); //bf.Serialize(stream, workspaceData); workspaceData.WriteData(writer); byte[] bytes = stream.ToArray(); //store byte arrays into the Workspace StoreBytes(mapping, unit.GetType(), bytes); } catch (SerializationException ex) { throw new WorkspaceException( String.Format( CultureInfo.CurrentCulture, "Object {0} for the given unit name '{1}' is not serializable and cannot be stored in the workspace.", unit.GetType().FullName, mapping), ex); } catch (InvalidOperationException ex) { throw new WorkspaceException( String.Format( CultureInfo.CurrentCulture, "Object {0} for the given unit name '{1}' cannot be stored in the workspace, because it is not serializable.", unit.GetType().FullName, mapping), ex); } }
/// <summary> /// Sets the data. /// Note that TraceLab during experiment execution uses SetDataBytes instead to avoid double serialization /// when crossing AppDomains border. /// </summary> /// <param name="data">The data.</param> private void SetData(object data) { lock (Serializer) { if (data != null) { var dataType = data.GetType(); if (dataType.IsClass && !dataType.IsEnum && dataType != typeof(string) && dataType.GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic, null, Type.EmptyTypes, null) == null) { throw new SerializationException("Object must have a parameterless constructor"); } var workspaceData = new WorkspaceUnitData(data); Serializer.Serialize(workspaceData); //store also data type, so it can be accessed without deserialization Type = dataType; OnPropertyChanged("Data"); } } }
/// <summary> /// Sets the data. /// Note that TraceLab during experiment execution uses SetDataBytes instead to avoid double serialization /// when crossing AppDomains border. /// </summary> /// <param name="data">The data.</param> private void SetData(object data) { lock (Serializer) { if (data != null) { var dataType = data.GetType(); if (dataType.IsClass && !dataType.IsEnum && dataType != typeof(string) && dataType.GetConstructor(System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic, null, Type.EmptyTypes, null) == null) { throw new SerializationException("Object must have a parameterless constructor"); } var workspaceData = new WorkspaceUnitData(data); Serializer.Serialize(workspaceData); //store also data type, so it can be accessed without deserialization Type = dataType; OnPropertyChanged("Data"); } } }
public void WorkspaceDataConstructorNullTest() { object data = null; WorkspaceUnitData target = new WorkspaceUnitData(data); }
public void InvalidXmlReaderThrows() { var data = new TraceLab.Core.Test.Workspaces.TestObject(); data.Value = "this is a test"; System.Xml.Serialization.IXmlSerializable target = new WorkspaceUnitData(data); target.ReadXml(null); }
public void SchemaIsNull() { var data = new TraceLab.Core.Test.Workspaces.TestObject(); data.Value = "this is a test"; System.Xml.Serialization.IXmlSerializable target = new WorkspaceUnitData(data); Assert.IsNull(target.GetSchema()); }
public void XmlSerializeTest() { var data = new TraceLab.Core.Test.Workspaces.TestObject(); data.Value = "this is a test"; WorkspaceUnitData target = new WorkspaceUnitData(data); var stream = new System.IO.MemoryStream(); var formatter = new System.Xml.Serialization.XmlSerializer(typeof(WorkspaceUnitData)); Assert.IsTrue(stream.Length == 0); formatter.Serialize(stream, target); Assert.IsTrue(stream.Length > 0); stream.Position = 0; var result = (WorkspaceUnitData)formatter.Deserialize(stream); var resultData = (TraceLab.Core.Test.Workspaces.TestObject)result.Data; Assert.AreEqual(data.Value, resultData.Value); }
public void RawBinarySerializeTest() { var data = new TraceLab.Core.Test.Workspaces.TestObject(); data.Value = "this is a test"; WorkspaceUnitData target = new WorkspaceUnitData(data); var stream = new System.IO.MemoryStream(); var writer = new System.IO.BinaryWriter(stream); Assert.IsTrue(stream.Length == 0); target.WriteData(writer); Assert.IsTrue(stream.Length > 0); stream.Position = 0; var result = (WorkspaceUnitData)Activator.CreateInstance(typeof(WorkspaceUnitData), true); result.ReadData(new System.IO.BinaryReader(stream)); var resultData = (TraceLab.Core.Test.Workspaces.TestObject)result.Data; Assert.AreEqual(data.Value, resultData.Value); }
public void IsTemporaryTest() { WorkspaceUnitData target = new WorkspaceUnitData(new TraceLab.Core.Test.Workspaces.TestObject()); bool expected = true; bool actual; target.IsTemporary = expected; actual = target.IsTemporary; Assert.AreEqual(expected, actual); expected = false; target.IsTemporary = expected; actual = target.IsTemporary; Assert.AreEqual(expected, actual); }
public void DataTest() { WorkspaceUnitData target = new WorkspaceUnitData(new TraceLab.Core.Test.Workspaces.TestObject()); // TODO: Initialize to an appropriate value object expected = new TraceLab.Core.Test.Workspaces.TestObject(); object actual = null; target.Data = expected; actual = target.Data; Assert.AreEqual(expected, actual); }