The method is supposed to be universal so it can be used together with other collector methods. In our codebase there already are extensions like:
.WhereElementIsAssemblyInstance()
.WhereElementIsLevel()
.WhereElementIsFamilyInstance()
So your example in our codebase would look like this when its also nessesary to filter on level name:
FilteredElementCollector collector = new FilteredElementCollector(doc)
.WhereElementIsLevel()
.WhereElementNameIs("SE51");
Unfortunately we need to have the class type specified as well so the last line ends up beeing
.WhereElementNameIs<Level>("SE51");
Which isnt optimal, but close enough to be usefull.
As to your second question, having the extensions on the collector allows us to chain additional filters on should the need arise. Sometimes we need to check for type (not class) as well, which is another extension method.
The internals of WhereElementNameIs could probably be optimised a bit, however there may be elements that require a different aproach.
To take an example, AssemblyInstance does not have a matching BIP for name as it seems to be inherited from its type (as far as I can tell), so to get it, I would have to look up the AssemblyType which does have a name in SYMBOL_NAME_PARAM. Then use the Id of that one to make a filter that matches ELEM_TYPE_PARAM which AssemblyInstance does have.
I tried it out and it does work, so the filtering logic for assembly instances ends up beeing:
else if (type == typeof(AssemblyInstance))
{
FilterRule assemblyTypeRule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.SYMBOL_NAME_PARAM), name, true);
ElementParameterFilter assemblyTypeFilter = new ElementParameterFilter(assemblyTypeRule);
AssemblyType assemblyType = new FilteredElementCollector(document)
.WherePasses(assemblyTypeFilter)
.WhereElementIsAssemblyTypeAsEnumerable()
.FirstOrDefault();
if (assemblyType == null) return collector;
FilterRule rule = ParameterFilterRuleFactory.CreateEqualsRule(new ElementId(BuiltInParameter.ELEM_TYPE_PARAM), assemblyType.Id);
ElementParameterFilter filter = new ElementParameterFilter(rule);
return collector.WherePasses(filter);
}
Where the "AsEnumerable" method is another homemade extension that simple does a cast:
public static IEnumerable<AssemblyType> WhereElementIsAssemblyTypeAsEnumerable(this FilteredElementCollector collector)
{
return
collector
.WhereElementIsAssemblyType()
.Cast<AssemblyType>();
}
In order to this I do need the document though, so it will have to added as a parameter since there is no way to get it from the collector that is passed in, thus the final calling code becomes:
var collector = new FilteredElementCollector(document)
.WhereElementNameIs<AssemblyInstance>(document, "SE51")
.WhereElementIsAssemblyInstance();