/// <summary> /// Try to get the mapping from MetaTree. If the data are not in the tree, try to create and add it. /// </summary> internal static PlcObject GetMapping(string name, ITree tree, Type t, bool allowAddingWithoutMappingAttribute = false) { if (string.IsNullOrWhiteSpace(name)) { return(null); } var nodePathStack = new Stack <string>(); nodePathStack.Push(RootNodeName); nodePathStack.Push(InstancesNodeName); foreach (var part in name.Split('.')) { nodePathStack.Push(part); } var path = PlcMetaDataTreePath.CreateAbsolutePath(nodePathStack.Reverse().ToArray()); var offset = 0; if (!tree.TryGet(path, ref offset, out var obj, true)) { if (t == null) { ExceptionThrowHelper.ThrowArgumentNullException(nameof(t)); } var mapping = t.GetTypeInfo().GetCustomAttributes <MappingAttribute>().FirstOrDefault(m => m.Name == name); if (mapping != null) { nodePathStack.Pop(); var plcObj = new PlcObjectRef(name, GetMetaData(tree, t)) { Offset = { Bytes = mapping.Offset }, Selector = mapping.Selector }; PlcObject.AddPlcObjectToTree(plcObj, tree, PlcMetaDataTreePath.CreateAbsolutePath(nodePathStack.Reverse().ToArray())); obj = plcObj; } else if (allowAddingWithoutMappingAttribute) { nodePathStack.Pop(); var plcObj = new PlcObjectRef(name, GetMetaData(tree, t)); PlcObject.AddPlcObjectToTree(plcObj, tree, PlcMetaDataTreePath.CreateAbsolutePath(nodePathStack.Reverse().ToArray())); obj = plcObj; } else { ExceptionThrowHelper.ThrowInvalidMappingNameException(name); } } return(obj as PlcObject); }
/// <summary> /// Try to get Meta data from MetaTree. If the data are not in the tree, try to create and add it. /// All the calculation of the offsets will be made in this method. the tree has two parts, one for MetaData and one for The Mappings. /// The mappings have only a Reference of the Meta data, so you shouldn't change the Offsets while using. /// </summary> private static PlcObject GetMetaData(ITree tree, Type t) { var nodePathStack = new Stack <string>(); var name = NormalizeTypeName(t.FullName); nodePathStack.Push(RootNodeName); nodePathStack.Push(MetaDataNodeName); nodePathStack.Push(name); var path = PlcMetaDataTreePath.CreateAbsolutePath(nodePathStack.Reverse().ToArray()); var offset = 0; if (!tree.TryGet(path, ref offset, out var obj)) { var byteOffset = 0; var bitOffset = 0; nodePathStack.Pop(); var parent = new PlcStruct(name, t); PlcObject.AddPlcObjectToTree(parent, tree, PlcMetaDataTreePath.CreateAbsolutePath(nodePathStack.Reverse().ToArray())); nodePathStack.Push(parent.Name); PlcObject pred = null; DebugOutPut("{0}{{", name); foreach (var pi in t.GetTypeInfo().DeclaredProperties) { var plcObject = PlcObjectFactory.CreatePlcObject(pi); if (plcObject is PlcArray plcObjectArray && (plcObjectArray.LeafElementType ?? plcObjectArray.ArrayType) is PlcStruct) { plcObjectArray.ArrayType = GetMetaData(tree, plcObjectArray.ElemenType); } else if (plcObject is PlcStruct) { plcObject = new PlcObjectRef(plcObject.Name, GetMetaData(tree, pi.PropertyType)); } var hasCustomOffset = PlcObjectFactory.GetOffsetFromAttribute(pi, ref byteOffset, ref bitOffset); AddPlcObject(tree, pred, plcObject, nodePathStack, ref byteOffset, ref bitOffset, hasCustomOffset); pred = plcObject; }