I'd propose to vary your first approach in order to avoid mixing presentation logic with the domain classes. You could add a product type identifier to IProduct
and set up the views for the products after a certain scheme that contains the product type identifier. When showing a view for a product, you build the view name after the scheme and integrate the product type identifier.
The advantage of this approach is that you'd follow a convention-over-configuration pattern that would not require to have an explicit configuration that maps the product types to a view.
As for your second approach: Instead of having a large switch statement in the factory that maps a domain class to a view, you could add a registry that contains the view that is assigned to a specific type. This would be better extensible.
Both approaches imply the risk that the presentation logic does not provide a view for a new domain class. You'd have to check whether a view (or registration respectively) exists for a product type in order to handle this properly. A possible way would be to provide a default view that shows the properties that are available in IProduct
for all classes. In addition, you should log an clear error message for the developer/administrator (see this link for a method to check whether a view exists).