I think you are somewhat misunderstanding what the Open-Closed principle entails.
The open-closed principle states that software entities should be closed for modification and open to extension. Software entities in this context refers to classes, structs methods etc.
The basic idea is that your entities should not need to change often to requirements. If new requirements come along, your entities should be extended to accommodate the new functionality.
Suppose we have the following function:
public List<Product> GetProducts(Criteria criteria)
{
return context.Where(x => x.criteria1 = criteria.criteria1)
.Where(x => x.criteria2 = criteria.criteria2)
.Where(x => x.criteria3 = criteria.criteria3)
.Where(x => x.criteria4 = criteria.criteria4);
}
It is easy to see that when another criteria requirement comes along, this will require modification to the "ProductRepository" class and it's functions. Ofcourse, many more functions in this class might need to be modified as it may also use criteria objects.
Suppose we can write something like this instead:
private List<Product> GetProducts(Criteria criteria)
{
return cleverContext.Apply(criteria);
}
We immediately gain the flexibility where only the code that is responsible for the criteria is modified or extended.
The biggest ways of improving design to satisfy the Open-Closed principle is to use a rich domain. When your domain models enterprise business rules, the rules should never change. We separate Domain with Use-Cases to deal with application rules.
Uncle bob writes more on this in his clean architecture.
Let me know if there is anything that I can shed light on, or try to explain further :)