Port to Port Logic


#1

My diagram is full of only objects which have a parent-to-child relationship. Each child node has a port called ‘InPort’ and there will always be only one link (or no links) to it. If there is a link, it will connect to some port on the parent. From the child, I’d like to be able to return the port I’m currently connected to on the parent.
I’ll attach the code I’m currently using, but I’ve just got to believe there’s a better way. Any suggestions? Thanks guys.

/// 
/// Gets the port on the schedule parent where this node is connected.
///

public GoPort ScheduleParentPort
{
get
{
// Could be schedule with no ‘In’ port
if (inPort == null) return null;
		// Could not be connected
if (inPort.SourceLinksCount == 0) return null;
		// Get the links
GoPortFilteredLinkEnumerator Links = inPort.SourceLinks;
		// Move to first link
Links.MoveNext;
		// Return the link port
return Links.Current.FromPort;
}
}

#2

P.S. If nothing else, I’d like to just use inPort.SourceLinks[0] instead of having to go through the mess of starting the enumerator. But since SourceLinks isn’t an arrary or collection (it’s just an enumerator) that isn’t an option. Is that possible? Or is there even a more efficient way then what I’m thinking?
As a side note: If SourceLinks returned an IGoLink[] rather then a GoPortFilteredLinkEnumerator it would be read only, you could access it by index, and it would even be enumerable. (Remember, any array is automatically enumerable.) Is there a reason that only an enumerator is returned?


#3

I suppose we could add a First property, much like what GoCollection has.
For flexibility and efficiency, we don’t want to be returning an array. It’s rather unfortunate that GoPortFilteredLinkEnumerator is public at all–that’s a side-effect of the quest for efficiency; people really shouldn’t be using enumerators explicitly in their source code.
But it sounds like what you’re doing is the right thing, and as an additional benefit, the value of the property is declared to be the class that you want.


#4

I agree that a ‘First’ property would work in this case, but what if I wanted the second link? Say for instance that the first link to me is always my parent, but any additional links will always be siblings. How do I get to those? Do I have to use an enumerator? Is there no way to access the links by index? I understand the foreach statement, but what if I want to use a simple FOR statement?
Remember, when using foreach you cannot remove an element from the collection. As you state in your own documentation, this is true of all .Net collections - they cannot be modified while being enumerated. But if you use a for loop starting from the last index and working your way toward 0, you CAN remove elements from the collection based on some criteria within your loop and it is safe to do so. How could I accomplish these sort of tasks when enumerating links?


#5

Using a FOR statement is still prone to potential errors.
What if the act of removing a particular link also caused other links to be removed? What if trying to remove a particular link failed? Even counting down from the last index might cause either skipping links or operating on them more than once.


#6

Fiar enough. But regardless of whether I’m deleting or not, there are probably hundreds of reasons I might want to be able to access an array of links - especially by index. Are you saying that I should have to use the interator to temporarily copy them all to my own array and then allow it to be garbage collected each time I do this? Or are you suggesting I should never want to do this in the first place?


#7

What if the act of removing a particular link also caused other links to be removed? What if trying to remove a particular link failed? Even counting down from the last index might cause either skipping links or operating on them more than once.
Also, please keep in mind that I am the author of this program. Obviously, it is my job to know the potential for problem. If there is a chance that removing a link will fail, I need to trap for that. Removing a link might cause other links to be removed, but it may not – it all depends on how I wrote it.
It should be up to me as the application developer to determine if this approach is valid or not. Otherwise, the vendor of a third-party control is injecting their business rules into my application. For the price we paid for an Enterprise subscription, I’m honestly a little surprised this is even part of the discussion.
My initial question was how to find the port I’m connected to on my parent. As it stands, I know that the first link to my node will always be the parent. Two weeks from now it may always be the third link. The question still remains as to the most efficient way I would acheive this particular link – be it the first or the third. And as I understand it currently, the answer is to initialize the iterator and move it x number of times. All I need to know is if that is the most efficient way to accomplish what we need.
I know there is probably a hint that I can catch for a link being added and removed. I could keep an internal counter and increment it each time a link is added and decrement it each time the link is removed. Then when I hit the magical link number I could hold on to the port at the other end. I also could probably write code into the higher-level document manager to assign properties when the two objects are linked together. But what would be easiset to me is to always return the remote port on link X (which happens to be 0 at this point).
The point is that I can code around only having access to an iterator in several ways. I mainly wanted to make sure that’s what I had to do.


#8

I still think you are doing the right thing, using the enumerator. I would write it as:
public GoPort ScheduleParentPort {
get {
if (inPort != null) {
foreach (IGoLink link in inPort.SourceLinks) {
return link.FromPort as GoPort;
}
}
return null;
}
}
Caveat! I haven’t even tried compiling this.
If you’re really worried about performance, I think there’s extra overhead involved with counting the SourceLinks (or the DestinationLinks), that you don’t need since you just want to know if there are any.
Furthermore, the current implementation uses a single ArrayList to hold all the links connected at a port. So you should try to add the parent link first before adding links to other nodes.