Как уже сказали все, вы захотите использовать контейнер IoC * или DI **. Но они не сказали, почему это так.
Идея состоит в том, что контейнер DI позволит вам обойти стратегию построения контроллера ASP.NET MVC по умолчанию, требующую конструктор без параметров. Таким образом, вы можете сделать так, чтобы ваши контроллеры явно указывали свои зависимости (как предпочтительно интерфейсы). То, как эти интерфейсы отображаются на конкретные экземпляры, является делом контейнера DI, и вы должны настроить его либо в Global.asax.cs (в режиме реального времени), либо в настройках своего тестового оборудования (для модульного тестирования).
Это означает, что вашему контроллеру не нужно ничего знать о конкретных реализациях его зависимостей, и поэтому мы следуем Принципу инверсии зависимостей : «Модули высокого уровня не должны зависеть от модулей низкого уровня. И то, и другое должно зависеть от абстракций. "
Например, если бы вы использовали AutoFac, вы бы сделали это:
// In Global.asax.cs's Application_Start
using Autofac;
using Autofac.Integration.Mvc;
var builder = new ContainerBuilder();
builder.RegisterControllers(Assembly.GetExecutingAssembly());
builder.Register<IRepository>(() => new ConcreteRepo());
var container = builder.Build();
DependencyResolver.SetResolver(new AutofacDependencyResolver(container));
// In your unit test:
var controllerInstance = new SampleController(new InMemoryFakeRepo());
// In SampleController
public class SampleController : Controller
{
private readonly IRepository _repo;
public SampleController(IRepository repo)
{
_repo = repo;
}
// No parameterless constructor! This is good; no accidents waiting to happen!
// No dependency on any particular concrete repo! Excellent!
}
* IoC = инверсия управления
** DI = инверсия зависимостей
(эти два термина часто взаимозаменяемы, что не совсем верно для ИМО)