/// <summary> /// Calculates total size in bytes of all public properties of an object /// </summary> /// <param name="obj">object which properties size should be calculated</param> /// <returns>size in bytes of all public properties of an object</returns> public static UInt32 SizeOfPublicPropertiesWithModbusAttribute(object obj, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead, bool processSubproperties = false) { if (obj is List<object>) return SizeOfPublicPropertiesWithModbusAttribute(((List<object>)obj).ToArray(), accessType); if (obj == null) throw new ArgumentNullException(); UInt32 totalLengthInBytes = 0; foreach (var field in OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)) { if ((field.CanWrite) && (field.GetCustomAttributes(typeof(ModbusPropertyAttribute), false).Length != 0)) { foreach (var attr in field.GetCustomAttributes(typeof(ModbusPropertyAttribute), false)) { if (((ModbusPropertyAttribute)attr).Access >= accessType) { totalLengthInBytes += (UInt32)Marshal.SizeOf(field.PropertyType); break; } } } else { if ((processSubproperties)&&(field.CanWrite)) { if (!field.PropertyType.IsValueType && !field.PropertyType.IsEnum && field.PropertyType == typeof(String)) { Type typeSource = field.GetType(); object objTarget = Activator.CreateInstance(typeSource); totalLengthInBytes += SizeOfPublicPropertiesWithModbusAttribute(objTarget, accessType); } } } } return totalLengthInBytes; }
/// <summary> /// Sets all public properties of the object array to values from arrayValues /// </summary> /// <param name="obj">Destination object</param> /// <param name="arrayValues">Values to which this function sets properties of the object array</param> /// <returns>true on success, false otherwise</returns> /// <remarks>Values in arrayValues should be placed sequentionaly in the same order with object's properties definitions</remarks> public static bool SetObjectPropertiesValuesFromArray(ref object obj, object[] arrayValues, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead) { if (obj == null) throw new ArgumentNullException(); if (arrayValues == null) throw new ArgumentNullException(); if (OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj).Length >= arrayValues.Length) { //first we check that arrayValues has same value types with object properties int i = 0; foreach (var item in OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)) { if ((item.CanWrite) && (item.GetCustomAttributes(typeof(ModbusPropertyAttribute), false).Length != 0)) { foreach (var attr in item.GetCustomAttributes(typeof(ModbusPropertyAttribute), false)) { if (((ModbusPropertyAttribute)attr).Access >= accessType) { if (item.PropertyType == arrayValues[i].GetType()) { item.SetValue(obj, Convert.ChangeType(arrayValues[i], item.PropertyType),null); i++; } else return false; break; } } } } return true; } return false; }
/// <summary> /// Extracts values of object's public properties /// </summary> /// <param name="obj">object which properties values should be extracted</param> /// <returns>array of public properties values</returns> public static object[] GetObjectModbusPropertiesValuesArray(object obj, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead) { if (obj == null) throw new ArgumentNullException(); List<object> lstTypesOfClassMembers = new List<object>(); PropertyInfo[] membersOfClass = OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj); foreach (var item in membersOfClass) { if (GetTypeHelper.IsNumericType(item.PropertyType)) { if ((item.CanWrite) && (item.GetIndexParameters().Length == 0) && (item.GetCustomAttributes(typeof (ModbusPropertyAttribute), false).Length != 0)) { foreach (var attr in item.GetCustomAttributes(typeof(ModbusPropertyAttribute), false)) { if (((ModbusPropertyAttribute)attr).Access >= accessType) { lstTypesOfClassMembers.Add(item.GetValue(obj,null)); break; } } } } } return lstTypesOfClassMembers.ToArray<object>(); }
/// <summary> /// Extracts types of public properties of objects in array /// </summary> /// <param name="obj">array of objects which properties should be extracted</param> /// <returns>array of public properties types</returns> public static Type[] GetObjectModbusPropertiesTypeArray(object[] obj, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead) { if (obj == null) throw new ArgumentNullException(); List<Type> lstTypesOfClassMembers = new List<Type>(); foreach (var item in obj) { if (item == null) throw new ArgumentNullException(); PropertyInfo[] membersOfClass = OrderedGetter.GetObjectPropertiesInDeclarationOrder(item); foreach (var property in membersOfClass) { if (GetTypeHelper.IsNumericType(property.PropertyType)) { if ((property.CanWrite) && (property.GetCustomAttributes(typeof (ModbusPropertyAttribute), false).Length != 0)) { foreach (var attr in property.GetCustomAttributes(typeof(ModbusPropertyAttribute), false)) { if (((ModbusPropertyAttribute)attr).Access >= accessType) { lstTypesOfClassMembers.Add(property.PropertyType); break; } } } } } } return lstTypesOfClassMembers.ToArray<Type>(); }
public static Byte GetModbusObjectsHighestByte(object obj, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead) { if (obj == null) throw new ArgumentNullException(); if (!GetTypeHelper.IsNumericType(obj.GetType())) { for (int i = OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj).Length-1; i >=0; i--) { if ((OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)[i].CanWrite) && (OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)[i].GetCustomAttributes(typeof(ModbusPropertyAttribute), false).Length != 0)) { foreach (var attr in OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)[i].GetCustomAttributes(typeof(ModbusPropertyAttribute), false)) { if (((ModbusPropertyAttribute)attr).Access >= accessType) { obj = OrderedGetter.GetObjectPropertiesInDeclarationOrder(obj)[i].GetValue(obj,null); break; } } break; } } } switch (obj.GetType().Name) { case "Byte": { return (Byte)obj; } case "SByte": { return unchecked((Byte)((SByte)obj)); } case "UInt16": { return BitConverter.GetBytes((UInt16)obj).ElementAt<Byte>(BitConverter.GetBytes((UInt16)obj).Length - 1); } case "Int16": { return BitConverter.GetBytes((Int16)obj).ElementAt<Byte>(BitConverter.GetBytes((Int16)obj).Length - 1); } case "UInt32": { return BitConverter.GetBytes((UInt32)obj).ElementAt<Byte>(BitConverter.GetBytes((UInt32)obj).Length - 1); } case "Int32": { return BitConverter.GetBytes((Int32)obj).ElementAt<Byte>(BitConverter.GetBytes((Int32)obj).Length - 1); } case "UInt64": { return BitConverter.GetBytes((UInt64)obj).ElementAt<Byte>(BitConverter.GetBytes((UInt64)obj).Length - 1); } case "Int64": { return BitConverter.GetBytes((Int64)obj).ElementAt<Byte>(BitConverter.GetBytes((Int64)obj).Length - 1); } case "Single": { return BitConverter.GetBytes((Single)obj).ElementAt<Byte>(BitConverter.GetBytes((Single)obj).Length - 1); } case "Double": { return BitConverter.GetBytes((Double)obj).ElementAt<Byte>(BitConverter.GetBytes((Double)obj).Length - 1); } case "Decimal": { return BitConverterEx.GetBytes((Decimal)obj).ElementAt<Byte>(BitConverterEx.GetBytes((Decimal)obj).Length - 1); } default: { throw new ArgumentException(); } } }
public static void ConvertObjectsVaulesToRegisters(object[] values, uint startIndex, uint objectsCount, bool bigEndianOrder, out ModbusDataPoint<UInt16>[] forcedValues, Type firstElementType, ModbusRegisterAccessType accessType = ModbusRegisterAccessType.AccessRead) { //array of output 16bit values forcedValues = null; bool[] boolValues = null; //if firstElementType is boolean then all elements of array are considered to be boolean type also if (firstElementType == typeof(bool)) { if (startIndex + objectsCount > 2000) //can force maximum 2000 coils throw new ArgumentException(); Array.Resize(ref forcedValues, (int)(startIndex + objectsCount + 15) / 16); Array.Resize(ref boolValues, (int)(startIndex + objectsCount)); } Byte[] tempArrayOfBytes = null; int i = 0; //foreach (var value in values) for (UInt32 regVal = startIndex; regVal < startIndex + objectsCount; regVal++) { //if arrayType is bool - all elements must be bool if ((firstElementType == typeof(bool)) && (firstElementType != values[regVal].GetType())) throw new ArgumentException(); if (firstElementType == typeof(bool)) boolValues[i] = (bool)values[regVal]; //if another type if (values[regVal].GetType().IsValueType) //here we will process simple (only numeric) types { if (GetTypeHelper.IsNumericType(values[regVal].GetType())) { ConvertObjectValueAndAppendToArray(ref tempArrayOfBytes, values[regVal], bigEndianOrder); } else if (values[regVal].GetType() != typeof (bool)) throw new ArgumentException(); } else //here we will process properties (only numeric) from complex (class) types { object[] arrayOfObjectPropsValues = GetObjectModbusPropertiesValuesArray(values[regVal], accessType); for (int k = 0; k < arrayOfObjectPropsValues.Length; k++) { ConvertObjectValueAndAppendToArray(ref tempArrayOfBytes, arrayOfObjectPropsValues[k], bigEndianOrder); } } i++; } if (firstElementType == typeof(bool)) { Byte[] temp = new Byte[forcedValues.Length * 2]; new BitArray(boolValues).CopyTo(temp, 0); for (int valIndex = 0, byteIndex = 0; valIndex < forcedValues.Length && byteIndex < temp.Length; valIndex++, byteIndex += 2) { forcedValues[valIndex] = new ModbusDataPoint<UInt16>(); forcedValues[valIndex].Value = (UInt16)(temp[byteIndex] | temp[byteIndex + 1] << 8); } //Buffer.BlockCopy(temp, 0, forcedValues, 0, temp.Length); } else { Array.Resize(ref forcedValues, (tempArrayOfBytes.Length + 1) / 2); for (int valIndex = 0, byteIndex = 0; valIndex < forcedValues.Length && byteIndex < tempArrayOfBytes.Length; valIndex++, byteIndex += 2) { forcedValues[valIndex] = new ModbusDataPoint<UInt16>(); forcedValues[valIndex].Value = (UInt16)(tempArrayOfBytes[byteIndex] | tempArrayOfBytes[byteIndex+1] << 8); } } }