c# dependency injection advantages