Hi again,
I did some research into families, but I'm still stuck with the very specific problem that made me start the thread.
I'll explain it in detail and with screenshots, and I hope you can give me some advice.
This is a nested family. Both the faucet and the basin are itself Family Instances.
They both have a Parameter "cpiFitMatchKey", which I will use as an example here. The idea is to make this modifyable on an instance basis.

This shows an Instance of the Family used in a Revit Document. The selected faucet is now a subpart. The Property "cpiFitMatchKey" is Read-Only because, in this scope, it is treated like a Family Parameter (as explained above, it is originally an Instance Parameter, but on an Instance that is itself nested in another Family).
As a result, it is greyed out in the UI, and trying to set it via API results in an exception (which is good, as I wouldn't want to modify the Family!).

I want this Parameter modifyable, individually for each instance, so I create a new Instance Parameter "cpiFitMatchKey.Faucet" and associate the faucet's 'cpiFitMatchKey' with it.
I do the exact same thing for the basin.


Result:

So far, this does pretty much exactly what I want. When I set one of these Parameters, the respective subpart (of the Instance!) will be modified, and when exporting the model, the faucet and basin will have the updated cpiFitMatchKeys, while new instances of the entire basin family will have the old default values.
When setting Parameter values via Code, I check if the Parameter's Read-Only. If it is, I check if the Element I'm trying to modify is a FamilyInstance.
If it is, I get myself a FamilyManager and try to fetch the associated Parameter, using the same method as here:
http://adndevblog.typepad.com/aec/2016/02/revitapi-how-to-change-radius-of-connectorelement-how-to-g...
I will paste the important segment here so I can highlight the part where it breaks:
var sb = new StringBuilder();
foreach (var connectorPara in connectorElement.GetOrderedParameters())
{
foreach (FamilyParameter familyPara in doc.FamilyManager.Parameters)
{
foreach (Parameter associatedPara in familyPara.AssociatedParameters)
{
if (connectorPara.Id == associatedPara.Id && associatedPara.Element.Id == connectorElement.Id)
{
//associate parameter found
sb.AppendLine("'" + associatedPara.Definition.Name +
"(" + (BuiltInParameter)associatedPara.Id.IntegerValue +
")' <-> '" + familyPara.Definition.Name + "'");
}
}
}
}
(Note: I tried FamilyManager.GetAssociatedFamilyParameter() first, which never yielded any result whatsoever. Probably for the exact reason that I now come to.)
The two IDs in the highlighted comparison will never be identical.
What the method finds is the nested FamilyInstance inside the Family. Which is not the element I'm trying to access here, I'm trying to access the instance inside the basin instance in my revit document.
Even the type IDs of the two are different. In fact, I find nothing at all that connects the two.
As a result, while I can (by omitting the ID check from above code) retrieve the two associations
cpiFitMatchKey <-> cpiFitMatchKey.Faucet and
cpiFitMatchKey <-> cpiFitMatchKey.Basin,
I cannot tell which one of the two I must use.
The problem may not become obvious as long as we are talking faucets and basins; some indicators could surely be found to distinguish between the two.
But:
1. This should work generically. I don't want to need any knowledge about the elements I'm looking at.
2. These could actually be instances of the same type. Let's say the basin family had two faucets - two instances of the nested family in the basin family. The Parameters of these two could be associated differently, but otherwise they would be pretty much identical. So, when dealing with a faucet in my revit document, I need to know which faucet in the defining family it's a copy of.
TL;DR:
This leads me back to the original question of the thread:
How do I find out which subpart of a FamilyInstance corresponds to what subpart of a Family?
Alternatively: How do I tackle this differently to not have this problem in the first place? 😛