diff --git a/S7.Net.UnitTest/S7NetTestsAsync.cs b/S7.Net.UnitTest/S7NetTestsAsync.cs index 31f99eb..86d7f22 100644 --- a/S7.Net.UnitTest/S7NetTestsAsync.cs +++ b/S7.Net.UnitTest/S7NetTestsAsync.cs @@ -160,6 +160,31 @@ namespace S7.Net.UnitTest Assert.AreEqual(tc.DWordVariable, tc2.DWordVariable); } + [TestMethod] + public async Task Test_Async_ReadAndWriteNestedClass() + { + Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor."); + + TestClassWithNestedClass tc = new TestClassWithNestedClass + { + BitVariable00 = true, + BitVariable01 = new TestClassInnerWithBool { BitVariable00 = true }, + ByteVariable02 = new TestClassInnerWithByte { ByteVariable00 = 128 }, + BitVariable03 = true, + ShortVariable04 = new TestClassInnerWithShort { ShortVarialbe00 = -15000 } + }; + + await plc.WriteClassAsync(tc, DB4); + TestClassWithNestedClass tc2 = new TestClassWithNestedClass(); + // Values that are read from a class are stored inside the class itself, that is passed by reference + await plc.ReadClassAsync(tc2, DB4); + Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00); + Assert.AreEqual(tc.BitVariable01.BitVariable00, tc2.BitVariable01.BitVariable00); + Assert.AreEqual(tc.ByteVariable02.ByteVariable00, tc2.ByteVariable02.ByteVariable00); + Assert.AreEqual(tc.BitVariable03, tc2.BitVariable03); + Assert.AreEqual(tc.ShortVariable04.ShortVarialbe00, tc2.ShortVariable04.ShortVarialbe00); + } + /// /// Read/Write a struct that has the same properties of a DB with the same field in the same order /// diff --git a/S7.Net.UnitTest/S7NetTestsSync.cs b/S7.Net.UnitTest/S7NetTestsSync.cs index 1b648f2..c096643 100644 --- a/S7.Net.UnitTest/S7NetTestsSync.cs +++ b/S7.Net.UnitTest/S7NetTestsSync.cs @@ -718,6 +718,31 @@ namespace S7.Net.UnitTest Assert.AreEqual(tc.ShortVariable04.ShortVarialbe00, tc2.ShortVariable04.ShortVarialbe00); } + [TestMethod] + public void T32_ReadAndWriteNestedClass() + { + Assert.IsTrue(plc.IsConnected, "Before executing this test, the plc must be connected. Check constructor."); + + TestClassWithNestedClass tc = new TestClassWithNestedClass + { + BitVariable00 = true, + BitVariable01 = new TestClassInnerWithBool { BitVariable00 = true }, + ByteVariable02 = new TestClassInnerWithByte { ByteVariable00 = 128 }, + BitVariable03 = true, + ShortVariable04 = new TestClassInnerWithShort { ShortVarialbe00 = -15000 } + }; + + plc.WriteClass(tc, DB4); + TestClassWithNestedClass tc2 = new TestClassWithNestedClass(); + // Values that are read from a class are stored inside the class itself, that is passed by reference + plc.ReadClass(tc2, DB4); + Assert.AreEqual(tc.BitVariable00, tc2.BitVariable00); + Assert.AreEqual(tc.BitVariable01.BitVariable00, tc2.BitVariable01.BitVariable00); + Assert.AreEqual(tc.ByteVariable02.ByteVariable00, tc2.ByteVariable02.ByteVariable00); + Assert.AreEqual(tc.BitVariable03, tc2.BitVariable03); + Assert.AreEqual(tc.ShortVariable04.ShortVarialbe00, tc2.ShortVariable04.ShortVarialbe00); + } + [TestMethod, ExpectedException(typeof(PlcException))] public void T18_ReadStructThrowsIfPlcIsNotConnected() { diff --git a/S7.Net/PlcAsynchronous.cs b/S7.Net/PlcAsynchronous.cs index f3457ae..1c28503 100644 --- a/S7.Net/PlcAsynchronous.cs +++ b/S7.Net/PlcAsynchronous.cs @@ -370,8 +370,9 @@ namespace S7.Net /// A task that represents the asynchronous write operation. public async Task WriteClassAsync(object classValue, int db, int startByteAdr = 0) { - var bytes = Types.Class.ToBytes(classValue).ToList(); - await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes.ToArray()); + byte[] bytes = new byte[(int)Class.GetClassSize(classValue)]; + Types.Class.ToBytes(classValue, bytes); + await WriteBytesAsync(DataType.DataBlock, db, startByteAdr, bytes); } private async Task ReadBytesWithSingleRequestAsync(DataType dataType, int db, int startByteAdr, int count) diff --git a/S7.Net/Types/Class.cs b/S7.Net/Types/Class.cs index c1dc14f..227a521 100644 --- a/S7.Net/Types/Class.cs +++ b/S7.Net/Types/Class.cs @@ -239,7 +239,7 @@ namespace S7.Net.Types return numBytes; } - private static void ToBytes(object propertyValue, byte[] bytes, ref double numBytes) + private static double SetBytesFromProperty(object propertyValue, byte[] bytes, double numBytes) { int bytePos = 0; int bitPos = 0; @@ -282,7 +282,7 @@ namespace S7.Net.Types bytes2 = Single.ToByteArray((float)propertyValue); break; default: - bytes2 = ToBytes(propertyValue); + numBytes = ToBytes(propertyValue, bytes, numBytes); break; } @@ -297,6 +297,8 @@ namespace S7.Net.Types bytes[bytePos + bCnt] = bytes2[bCnt]; numBytes += bytes2.Length; } + + return numBytes; } /// @@ -304,12 +306,8 @@ namespace S7.Net.Types /// /// The struct object /// A byte array or null if fails. - public static byte[] ToBytes(object sourceClass) + public static double ToBytes(object sourceClass, byte[] bytes, double numBytes = 0.0) { - int size = (int)GetClassSize(sourceClass); - byte[] bytes = new byte[size]; - double numBytes = 0.0; - var properties = GetAccessableProperties(sourceClass.GetType()); foreach (var property in properties) { @@ -319,15 +317,15 @@ namespace S7.Net.Types Type elementType = property.PropertyType.GetElementType(); for (int i = 0; i < array.Length && numBytes < bytes.Length; i++) { - ToBytes(array.GetValue(i), bytes, ref numBytes); + numBytes = SetBytesFromProperty(array.GetValue(i), bytes, numBytes); } } else { - ToBytes(property.GetValue(sourceClass, null), bytes, ref numBytes); + numBytes = SetBytesFromProperty(property.GetValue(sourceClass, null), bytes, numBytes); } } - return bytes; + return numBytes; } } }