/// <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; }
/// <summary> /// Get all leafs from the meta tree, normally this should b only value types. /// </summary> /// <param name="obj">TreeNode</param> /// <param name="path">Path to node</param> /// <returns>List of leafs</returns> public static IEnumerable <string> GetLeafs(ITreeNode obj, ICollection <string> path) { var list = new List <string>(); if (obj != null) { var idx = obj.Name.IndexOf("[", StringComparison.Ordinal); if (idx >= 0) { var p = path.Last(); path = new List <string>(path.Take(path.Count - 1)) { p + obj.Name.Substring(idx) }; } else { path.Add(obj.Name); } if (obj.Childs.Any()) { if (obj is PlcArray) { foreach (var child in obj.Childs) { if (child.Childs.Any()) { var nunmberOfChilds = child.Childs.Count(); var internalPath = new List <string>(path.Take(path.Count - 1)) { obj.Name + child.Name }; foreach (var c in child.Childs) { list.AddRange(GetLeafs(c, internalPath.ToList())); } } else { var internalPath = new List <string>(path.Take(path.Count - 1)) { child.Name }; list.Add(PlcMetaDataTreePath.CreateAbsolutePath(internalPath.Skip(1).ToArray()).Path.Substring(1)); } } } else { foreach (var child in obj.Childs) { list.AddRange(GetLeafs(child, path.ToList())); } } } else { list.Add(PlcMetaDataTreePath.CreateAbsolutePath(path.Skip(1).ToArray()).Path.Substring(1)); } } return(list); }