Доброго времени суток.
На самом деле задача решается достаточно просто, причем даже без рекурсии.
Предполагаю, что doc - документ семейства (открытый через EditFamily или текущий документ семейства)
Замену параметров нужно делать в текущем doc.OwnerFamily + получить все общие семейства, заменить в них параметры и загрузить обратно в документ, этого достаточно.
Общие семейства получаем вот так:
var collector = new FilteredElementCollector(doc);
return collector
.OfClass(typeof(Family))
.OfType<Family>()
.Where(x => !x.IsOwnerFamily && x.IsShared());
Сама замена параметра осуществляется в 2 этапа:
1) замена общего параметра на параметр семейства с помощью метода
public FamilyParameter ReplaceParameter(
FamilyParameter currentParameter,
string parameterName,
BuiltInParameterGroup parameterGroup,
bool isInstance
)
//Replace a shared family parameter with a new non-shared family parameter
Тонкость: parameterName не может совпадать с именем общего параметра
2) замена параметра семейства на новый общий параметр
public FamilyParameter ReplaceParameter(
FamilyParameter currentParameter,
ExternalDefinition familyDefinition,
BuiltInParameterGroup parameterGroup,
bool isInstance
)
// Replace a family parameter with a shared parameter.
Есть еще только один подводный камень, связанный с заменой параметров во вложенных семействах. В ревите уже может быть открыто семейство с таким именем, причем, оно может не совпадать со вложеным от слова "совсем", в общем, рекомендую проверять application.Documents перед тем, как пытаться заменять параметры во вложенных семействах