Use dynamic
to select appropriate method overload at runtime:
public class RenderManager
{
public void Render(IPage page, Renderer renderer)
{
try
{
renderer.RenderPage((dynamic)page);
}
catch (RuntimeBinderException ex)
{
throw new Exception("Page type not supported", ex);
}
}
}
But of course dynamic typing has performance costs. Benefits - when new type of page added, all you need to change is renderer - just add another overloaded method.
Another option is visitor. In this case each page should do dispatching (seems like your second approach):
public interface IPage
{
void Render(Renderer renderer);
}
public class StaticPage : IStaticPage
{
public void Render(Renderer renderer)
{
renderer.RenderPage(this);
}
}
public class RenderManager
{
public void Render(IPage page, Renderer renderer)
{
page.Render(renderer);
}
}
In this case page 'knows' about rendering. And you still should modify renderer when adding new pages.