I really had no idea how to title this question but try and understand my question :)
I am trying to learn C#, creating a sample project. I want to know how I can iterate trough a collection which contains interfaces, these interfaces have children with their own interfaces and so on and so forth. The depth is unknow and different for every client I would connect to. I know how I would do it in nested foreach loops, but as I just mentioned, the depth is uknown and I know that the way my brain works right now - using for loops - is just dumb and there are better way of doing this without losing my mind wiring infinite foreach loops. The answer to this question will probably also answer my next question, which I might not post, since I feel like they are so related.
Here is my method that I could create N for loops, but I know there is a better way - probably reflection - I am only starting to read on it, so if anyone could give me an example of how to get these types, maybe in a while loop where I would just change the string of the property I am trying to find? I want to collect ALL ISymmbol.InstancePath
properties in the collection of ISymbolCollection<ISymbol>
and store them in the list of strings.
public static List<string> SymbolsCollection(AdsClient adsClient)
{
// List of symbol names as string that the method will return
List<string> symbols = new List<string>();
// The collection I receive from my client
ISymbolCollection<ISymbol> symbolCollection = GetSymbols(adsClient);
// Now loping the data inside the received collection
foreach(ISymbol symbol in symbolCollection)
{
// Example of how I store the first, topmost symbol to the list
symbols.Add(symbol.InstancePath);
// The symbol contains subsymbols - I need to store it in the list as well
foreach(ISymbol subsymbol in symbol.SubSymbols)
{
symbols.Add(subsymbol.InstancePath);
//Third time iterating
foreach(ISymbol subSymbolsSubsymbol in subsymbol.SubSymbols)
{
symbols.Add(subSymbolsSubsymbol.InstancePath);
// This could go really deep as you can see
}
}
}
return symbols;
}
Edit: The Isymbol interface:
public interface ISymbol : IAttributedInstance, IInstance, IBitSize
{
//
// Summary:
// Gets the Symbol/Datatype Category
//
// Value:
// The category.
DataTypeCategory Category { get; }
//
// Summary:
// Gets the parent Symbol
//
// Value:
// The parent.
ISymbol? Parent { get; }
//
// Summary:
// Gets the SubSymbols of the TwinCAT.TypeSystem.ISymbol
//
// Remarks:
// Used for Array, Struct, Pointer and Reference instances. Otherwise empty
ISymbolCollection<ISymbol> SubSymbols { get; }
//
// Summary:
// Gets a value indicating whether this Symbol is acontainer type.
//
// Value:
// true if this instance is container type; otherwise, false.
bool IsContainerType { get; }
//
// Summary:
// Gets a value indicating whether this instance is a primitive type.
//
// Value:
// true if this instance is primitive type; otherwise, false.
bool IsPrimitiveType { get; }
//
// Summary:
// Gets a value indicating whether this TwinCAT.TypeSystem.ISymbol is persistent.
//
// Value:
// true if this instance is persistent; otherwise, false.
bool IsPersistent { get; }
//
// Summary:
// Indicates that this instance is read only.
//
// Remarks:
// Actually, this Flag is restricted to TcCOM-Objects readonly Parameters. Within
// the PLC this is used for the ApplicationName and ProjectName of PLC instances.
// Write-Access on these Modules will create an TwinCAT.Ads.AdsErrorCode.DeviceAccessDenied
// error.
bool IsReadOnly { get; }
//
// Summary:
// Gets a value indicating whether this instance is recursive.
//
// Value:
// true if this instance is recursive; otherwise, false.
bool IsRecursive { get; }
}
}
Please let me know if my question is unclear or you need more information about the data types etc.
I am using .NET 6 framework. I could swap to 4.8 so I think that shouldn't matter in that case, so any solution for either framework will apply (all these frameworks are also confusing, as there are so many - I just went with the newest one when installing VS).