Когда вы используете инверсию контроля, вы помогаете вашему классу делать как можно меньше. Допустим, у вас есть служба Windows, которая ожидает файлы, а затем выполняет серию процессов над файлом. Один из процессов - преобразовать его в ZIP, а затем отправить по электронной почте.
public class ZipProcessor : IFileProcessor
{
IZipService ZipService;
IEmailService EmailService;
public void Process(string fileName)
{
ZipService.Zip(fileName, Path.ChangeFileExtension(fileName, ".zip"));
EmailService.SendEmailTo(................);
}
}
Зачем этому классу на самом деле делать архивирование и отправку по электронной почте, когда у вас могут быть специальные классы, чтобы сделать это для вас? Очевидно, что вы этого не сделаете, но это всего лишь вывод на мой счет: -)
В дополнение к отсутствию реализации Zip и электронной почты, почему класс должен знать, какой класс реализует службу? Если вы передаете интерфейсы конструктору этого процессора, то ему никогда не нужно создавать экземпляр определенного класса, ему дается все, что ему нужно для работы.
Использование D.I.C. вы можете настроить, какие классы реализуют определенные интерфейсы, а затем просто заставить его создать экземпляр для вас, он внедрит зависимости в класс.
var processor = Container.Resolve<ZipProcessor>();
Так что теперь вы не только четко отделили функциональность класса от разделяемой функциональности, но и не позволили потребителю / провайдеру иметь какие-либо явные знания друг о друге. Это делает чтение кода более простым для понимания, поскольку одновременно нужно учитывать меньше факторов.
Наконец, при модульном тестировании вы можете передать имитированные зависимости. Когда вы тестируете свой ZipProcessor, ваши поддельные сервисы будут просто утверждать, что класс пытался отправить электронное письмо, а не пытался его отправить.
//Mock the ZIP
var mockZipService = MockRepository.GenerateMock<IZipService>();
mockZipService.Expect(x => x.Zip("Hello.xml", "Hello.zip"));
//Mock the email send
var mockEmailService = MockRepository.GenerateMock<IEmailService>();
mockEmailService.Expect(x => x.SendEmailTo(.................);
//Test the processor
var testSubject = new ZipProcessor(mockZipService, mockEmailService);
testSubject.Process("Hello.xml");
//Assert it used the services in the correct way
mockZipService.VerifyAlLExpectations();
mockEmailService.VerifyAllExceptions();
Итак, вкратце. Вы хотели бы сделать это, чтобы
01: Не позволяйте потребителям явно знать, какой провайдер реализует необходимые им услуги, а это значит, что при чтении кода сразу становится меньше понимания.
02: Упростить модульное тестирование.
Пит