Страницы с тегами : Unity

Статьи про IoC, AOP и контейнер Unity

Первые посты про IoC я написал более двух лет назад, но судя по статистике блога люди часто к ним обращаются.

В этом после приведу индекс статей в порядке чтения для облегчения поиска и навигации

  1. Введение в IoC
  2. Основная задача IoC-контейнеров
  3. Первые шаги с Unity
  4. Рефакторинг legacy-кода для использования Unity
  5. Использование generic-классов с Unity
  6. Инъекция массивов в Unity
  7. Unity LifetimeManager
  8. Конфигурация Unity
  9. Инъекция самого контейнера Unity в объекты
  10. AOP в Unity
  11. Фабрики в Unity
  12. Практика AOP: аудит изменений данных в EF с учетом котнекста операций
  13. Unity 2.0
  14. AOP в Unity 2.0


Unity 2.0 Interception

Ранее я писал про механизмы AOP в Unity 1.0 (или 1.2 на тот момент). Недавно увидел этот пост, с примером для Unity 2.0.

В первой версии было фактически две возможности для задания перехватчиков вызовов: это атрибуты на классах или сложный код (или xml), задающий условия по которым будут срабатывать обработчики вызовов.

Оба варианта довольно плохие, первый заставляет править существующий код, второй просто неподъемный. В Unity 2.0 исправили ситуацию с помощью так называемых InterceptionBehavior.

Пример кода из поста в новом стиле.

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Practices.Unity;
using Microsoft.Practices.Unity.InterceptionExtension;
using System.Transactions;


                
                
                
                
            


Unity 2.0

Давненько я не писал про Unity. За это время успела выйти новая версия этого IoC-контейнера и появилась новая версия Enterprise Library.

Первое заметное изменение в Unity: теперь требуется подключать одну сборку Microsoft.Practices.Unity. Хотя AOP для Unity все еще лежит в отдельной сборке Microsoft.Practices.Unit.Interception.

Интерфейс класса UnityContainer расширился методами IsRegistered и свойством Registrations. Последнее позволяет анализировать что мы уже положили в контейнер.

Три больших изменения в резолвинге. 

  1. Теперь можно резолвить Func<T>, который будет возвращать зарегистрированный в контейнере экземпляр T. Аналогично можно резолвить Func<IEnumerable<T>>, который будет возвращать все зарегистрированные в контейнере именованные зависимости типа T. Это дает возможность переконфигурировать контейнер во время работы программы, так чтобы остальной код об этом не знал.
  2. При наличии нескольких конструкторов в создаваемом классе по-умолчанию выбирается конструктор с максимальным количеством параметров.
  3. В метод Resolve теперь можно передавать объекты ResolverOverride, позволяющие переопределять поведение Unity при резолвинге.

Добавились два LifetimeManager. HierarchicalLifetimeManager – чтобы дочерние контейнеры резолвили свои экземпляры, а не брали родительский. Это может пригодиться в вебе при создании дочерних контейнеров на каждый запрос. PerResolveLifetimeManager – позволяет переиспользовать один экземпляр в пределах одного вызова метода Resolve.

Подробнее можно почитать в Change Log.

PS. Также есть версия для Silverlight.

PPS. Качать здесь.



Аудит изменений с учетом контекста операций

В предыдущем посте я описал способ, который позволяет проводить аудит изменений данных в Entity Framework, не затрагивая сами классы сущностей.

Аудит изменений данных вполне возможно делать в самой БД с помощью триггеров, но в базу не попадают сведения о том какой пользователь системы произвел изменения (в случае приложения, построенного по принципу trusted subsystem) и с какой целью были проведены эти изменения.

Для каждой операции работы изменения данных существует некоторый контекст, который включает в себя как некоторые явные параметры, как имя пользователя или URL, так и неявные, например намерения, с которыми были выполнены изменения данных (частично их можно восстановить по стеку вызовов).

Для задач логирования было бы удобно иметь доступ к некоторым параметрам контекста, особенно неявным. Эти параметры должны прозрачно передаваться по цепочке вызовов. Для решения таких задач можно применить монады, но тогда придется переписать весь код под использование монад, что очень проблематично. Можно воспользоваться возможностями AOP и IoC чтобы обеспечить неявную передачу явного контекста.

Для начала нам понадобится класс для хранения текущего контекста. Как и в случае со стеком вызовов, контексты тоже могут составлять некоторый стек.

public interface IContextManager<T>
{
    void Push(T value);
    void Revert();
    IEnumerable<T> GetValues();
}


Паттерн MVVM. Часть 1.

MVVM – Model – View – ViewModel – паттерн организации PL (presentation layer – уровень представления).

Паттерн MVVM применяется при создании приложений с помощью WPF и Silverlight.   Этот паттерн был придуман архитектором этих самых WPF и Silverlight - John Gossman (его блог). Паттерн MVVM применяется в Expression Blend.

Идеологически MVVM похож на Presentation Model описанный небезызвестным Фаулером, но MVVM сильно опирается на возможности WPF.

Основная особенность MVVM заключается в том, что все поведение выносится из представления (view) в  модель представления (view model).  Связывание представления и модели представления осуществляется декларативными байндингами в XAML разметке. Это позволяет тестировать все детали интерфейса не используя сложных инструментальных средств.

Я сначала хотел кратко описать применение MVVM и Unity для построения PL, но понял что одного поста для описания возможностей MVVM очень мало.

В WPF для передачи данных между объектами и визуальными элементами используются байндинги (binding – привязка) в простонародии биндинги. Передача может быть как однонаправленная, так и двунаправленная. Работают байндинги с помощью зависимых свойств (DependencyProperty) или интерфейса INotifyPropertyChanged. Передача управляющих воздействий от визуальных элементов осуществляется с помощью команд, реализующих интерфейс ICommand.

Для начала надоевший уже пример SayHello.

Как всегда используется супер-сложный класс бизнес логики:

public interface ISayHelloService
{
    string SayHello(string name);
}
 
public class SayHelloSerivce : ISayHelloService
{
    public string SayHello(string name)
    {
        return "Привет, " + name;
    }
}


Паттерн MVP и Unity

MVP – Model View Presenter – паттерн организации PL (presentation layer – уровень представления).

MVP применяется при создании десктопных интерфейсов. Выделяют три комопнента: есть модель – группа классов, которые отдают данные или получают команды, представление – форма обладающая состоянием и некоторым поведением. Презентер создают для отделения бизнес-логики от деталей GUI-фреймворка. В отличие от MVC в MVP представление определяет презентер, а не наоборот.

MVP обычно строится вокруг существующих GUI-фреймворков. На практике существуют две принципиально различные различные реализации паттерна – Supervising Controller и Passive View.
В первом случае логика помещается в обработчики событий button_click, а сами обработчики помещаются в отдельный класс. Для полной изоляции презентера от деталей представления надо писать достаточно много врапперов\адаптеров.
Во втором случае создается пара интерфейсов для общения между представлением и презентером. При совершении какого-либо действия представление напрямую обращается к презентеру, тот выполняет некоторый код и вызывает установку свойств представления. Passive View способствует максимальному перемещению кода в в презентер, что облегчает тестирование.

Создание MVP в WinForms с помощью Unity.

Создаем новое winforms приложение и грохаем оттуда форму.

Для начала определим служебные интерфейсы.

//Маркерный интерфейс представления
public interface IView
{
}


                
            


Unity + ASP.NET MVC

Недавно на хабре появилась статья о Unity. В одном из комментов предложили связать ASP.NET MVC и Unity.

А вот есть прикольная задачка уже не для начинающих — связать ASP.NET MVC с Unity. Требований в целом три:

— обеспечить связывание инфраструктуры контроллеров MVC с инъектором
— модульность
— уникальность контейнера в разрезе сессии

Я бы расписал все, но блин, не успеваю вообще ничего, кроме работы. А вам в рамках обучающих методик будет полезно, имхо.

хабраюзер acerv

Я напишу серию постов о применении Unity в паттернах уровня представления.

Сначала о том что такое MVC.

MVC – Model View Controller – паттерн организации PL (presentation layer – уровень представления). Целью этого паттерна, как и многих других, служит отделение модели (логики работы программы) от представления (средств отображения информации). В итоге применение такого паттерна должно приводить к улучшению тестируемости кода.

В современном виде MVC применяется в вебе. Выглядит так: есть модель – группа классов, которые отдают данные или получают команды, есть различные представления этих данных – HTML, сделанные с помощью какого-либо шаблонизатора, JSON, SOAP, XML или еще какой – либо. Для того чтобы передавать данные от модели к представления вводят контроллер.

Все MVC фреймворки проектируются так, чтобы управление приходило сразу на контроллер. Контроллер вызывает методы модели, если нужно формирует данные для передачи представлению (эти данные называют Presentation Entity, но термин неустоявшийся), и выбирает представление для этих данных.

ASP.NET MVC – фреймворк для ASP.NET, реализующий паттерн MVC.
Контроллеры в ASP.NET MVC – классы, унаследованные от класса Controller, содержащие несколько методов - “действий”  (actions). По умолчанию действия отображаются на различные urlы см помощью механизма раутинга (System.Web.Routing).
Каждое действие возвращает ActionResult, который может вызывать генерацию HTML, сериализацию данных в JSON итд. Можно писать свои ActionResult.

Применение Unity в ASP.NET MVC.

Инфраструктура ASP.NET MVC получает имя контроллера из параметров запроса, формируемых механизмом раутинга, потом вызывает класс ControllerFactory, который по имени возвращает экземпляр контроллера.

Сначала создадим новое asp.net mvc приложение. Оно уже включает в себя большой функционал, его трогать не будем.

Чтобы подключить Unity к механизму создания контроллеров надо написать свой класс ControllerFactory.  По умолчанию используется DefaultControllerFactory, нам надо изменить в нем один метод, который создает объект контроллера.

public class UnityControllerFactory: DefaultControllerFactory
{
    IUnityContainer _container;


                
            


MEF

MEF – Managed Extensibility Framework – новая библиотека для создания композитных приложений. То есть приложений, которые собираются из отдельных частей.

Скачать его можно по адресу http://mef.codeplex.com/, версия на момент написания поста – Preview 5. На базе MEF построена Visual Studio 2010.

MEF по функциональности похожа на IoC-контейнеры, но авторы не стремились повторить функциональность существующих контейнеров. В MEF есть несколько уникальных фич, которых нету в  IoC-контейнерах.

Сразу примеры, снова поиск фильмов. Возьмем основной код из поста про Unity.

// Фильм
public class Movie
{
    public string Title { get; set; }
    public string Director { get; set; }
    public int Year { get; set; }
}


                
            


Применение Enterprise Library

Все возможности Enterprise Library можно применять по-отдельности и радоваться жизни. Но если бы это была единственная возможность я бы не написал этот пост.

Магия начинается в сборке Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers.
В этой сборке в одноименном неймспейсе содержатся call handlerы и атрибуты для навешивания обработчиков на методы. Как использовать call handlerы я рассказывал в этом посте.

Кратко опишу доступные хендлеры:

  • AuthorizationCallHandler – задействует Security Application Block для авторизации при вызове перехваченного метода
  • CachingCallHandler – обработчик, кеширующий результаты вызова перехваченного метода средствами Caching Application Block. Может быть чрезвычайно полезным для веб-разработки.
  • ExceptionCallHandler – позволяет декларативно задавать стратегию обработки исключений в перехваченном методе. Стратегии задаются средствами Exception Handling Application Block.
  • LogCallHandler – задействует Logging Application Block для логгирования вызова перехваченного метода.
  • ValidationCallHandler – вызывает валидацию параметров метода. Параметры валидации должны быть заданы атрибутами или в конфигурации Validation Application Block.
  • PerformanceCounterCallHandler – обработчик, который занимается сбором информации о параметрах быстродействия перехваченного метода. Информация сохраняется в PreformanceCounterах. В самой сборке Microsoft.Practices.EnterpriseLibrary.PolicyInjection.CallHandlers есть Installer (который можно запустить через installutil), создающий необходимые  счетчики производительности.

Если интересует только runtime AOP, то можно использовать не полновесный IoC-контейнер Unity, а легковесный генератор прокси-классов из Policy Injection Application Block.

Кроме перехватчиков вызовов существует другой способ интеграции всех application blocks с контейнером Uinty. Практический каждый application block из состава enterprise library содержит класс – расширение Unity, которое контейнер возвращать объекты-фасады при запросе определенных типов.

Все расширения можно найти в основной сборке application block, в неймспейсе Configuration.Unity. Классы расширений называются ИмяБлокаExtension.

  • Для Logging Application Block расширение заставляет Unity возвращать фасад логгера по запросу типа LogWriter.
  • Для Exception Handling Application Block  основной тип фасада – ExceptionManager.
  • Для Caching Application Block контейнер возвращает реализации интерфейсов ICacheManager, IStorageEncryptionProvider, IBackingStore.
  • Для Security Application Block контейнер возвращает реализации интерфейсов IAuthorizationProvider, ISecurityCacheProvider.
  • Для Data Access Application Block контейнер возвращает экземпляры класса Database, аналогично DatabaseFactory.CreateDatabase. Можно получать как экземпляр по-умолчанию, так и именованный экземпляр.
  • Для Cryptography Application Block (который находится в сборке Microsoft.Practices.EnterpriseLibrary.Security.Cryptography) расширение заставляет Unity возвращать фасад по запросу типа CryptographyManager, а также реализации интерфейсов IHashProvider и ISymmetricCryptoProvider.

При использовании application blocks совместно с unity все настройки блоков надо задавать в файле конфигурации. Для этого в Enterpise Library есть удобная утилита.

К сожалению я не смог придумать адекватного примера, который сможет показать хотя бы малую часть возможностей Enterprise Library с использованием Unity.



Введение в Enterpise Library

Enterprise Library – библиотека от группы patterns & practicies Microsoft. Проект живет по адресу http://www.codeplex.com/entlib.

Enterprise Library состоит из набора компонент, называемых application blocks, каждый из которых решает определенную задачу, часто возникающую при разработке ПО. 

В состав Enterprise Library входят следующие блоки:

  • Unity Application Block  - IoC-контейнер Unity
  • Policy Injection Application Block – AOP времени выполнения
  • Validation Application Block – небольшой фреймворк для валидации
  • Logging Application Block – логгер
  • Exception Handling Application Block – фреймворк для создания политик обработки исключений в приложении
  • Caching Application Block – фреймворк для кеширования
  • Security Application Block – библиотека для авторизации, практически повторение ASP.NET Membership
  • Data Access Application Block – библиотека, упрощающая работу с ADO.NET, используется другими блоками
  • Cryptography Application Block – библиотека для упрощения работы с криптографическими функциями в .NET

Все эти блоки могут настраиваться через config-файл, для этого в составе Enterprise Library есть утилита упрощающая этот процесс.

Почти все блоки можно использовать по-отдельности, но основная сила Enterprise Library состоит в том, что все блоки можно подключить через Unity.



Фабрики объектов в Unity

В этом посте я описал как с помощью LifetimeManager можно научить Unity использовать фабрику для создания объектов.

На самом деле так делать не стоит. В составе Unity есть сборка Microsoft.Practices.Unity.StaticFactory.dll в которой находится расширение контейнера для использования фабрики объектов.

Регистрация фабрики происходит методом RegisterFactory, который принимает делегат FactoryDelegate. Этот делегат принимает параметром IUnityContainer, и возвращает object.

Пример

var r = new Random();
var container = new UnityContainer();
container
    .AddNewExtension<StaticFactoryExtension>()
    .Configure<StaticFactoryExtension>()
        .RegisterFactory<int>("random", c => r.Next());


AOP времени исполнения в Unity

Для тех кто не знает – AOP это Aspect-Oriented Programming, Аспектно-ориентированное программирование.

При написании любой программы программист производит функциональную декомпозицию, то есть разбивает большие блоки функциональности на более маленькие. Но всегда существуют так называемые cross-cutting concerns  или сквозная функциональность, которая используется всеми остальными частями программы, которую невозможно выделить  в отдельный модуль\класс\метод,
Чаще всего такой функциональностью является логгирование, разграничение доступа, управление транзакциями.

Концепция AOP заключается в том что сквозная функциональность выделяется в отдельные сущности , называемые аспектами, и декларативно задается использование аспектов  в коде.

AOP для .NET может быть реализован двумя способами: изменение кода при компиляции инструментами типа PostSharp или макросами языка Nemerle, или перехват вызовов на стадии выполнения.

В составе Unity есть сборка Microsoft.Practices.Unity.Interception, которая содержит расширение контейнера Unity для перехвата вызовов объектов собираемых контейнером.

Чтобы перехватывать вызовы надо контейнеру сообщить что перехватывать, как перехватывать, и зачем перехватывать.
Что перехватывать задается политиками (Policy), как перехватывать определяют перехватчики (Interceptor), зачем перехватывать определяют обработчики вызовов (CallHandlers).
Эти три части механизма перехвата не зависят друг от друга.

Перехватчики – это классы, реализующие интерфейс IInterceptor. В библиотеке есть классы InterfaceInterceptor для перехвата методов интерфейса, VirtualMethodInterceptor – для перехвата виртуальных методов класса, TransparentProxyInterceptor – для перехвата с помощью прокси-классов, используемых для .NET Remoting.

Обработчики вызовов – это классы, которые реализуют интерфейс ICallHandler, в котором только один нужный метод – Invoke.

Политики бывают двух видов – управляемая атрибутами (AttributeDrivenPolicy) и управляемая правилами (RuleDrivenPolicy).
По-умолчанию используется AttributeDrivenPolicy, которая заключается в том что обработчики вызовов задаются атрибутами, унаследованными от HandlerAttribute, и перехватываются только те методы, для которых заданы эти атрибуты (или атрибуты заданы для классов).
RuleDrivenPolicy позволяет задавать какие методы будут перехватываться с помощью набора правил (IMatchingRule)  и какие обработчики будут при этом вызываться.

Подробнее по этой ссылке http://msdn.microsoft.com/en-us/library/dd140045.aspx

Если вы сами пишете код, для которого нужен перехват, то атрибутов и стандартной политики вам будет достаточно. Если вы не можете менять код классов, но хотите их перехватывать, то это можно сделать с помощью задания политик, основанных на правилах заданных в коде или конфигурационном файле.

Пример

Сначала создадим обработчик, который просто выводит Hello, world на консоль

public sealed class HelloWorldAttribute : HandlerAttribute
{
    public override ICallHandler CreateHandler(IUnityContainer container)
    {
        return new HelloWorldCallHandler();
    }
}


                
            


Что делать если Unity-контейнер надо передавать как зависимость в другие компоненты?

Правильный ответ – ничего.

var container = new UnityContainer();
var resolvedContainer = container.Resolve<IUnityContainer>();


Конфигурация Unity

Существует четыре различных способа конфигурирования контейнера.

1)Использование соглашений. Фактически отсутствие явного конфигурирования. В Unity используется очень простое соглашение, что в классе должен быть один конструктор, который принимает все зависимости параметрами.
Такой способ подходит для 90% случаев если вы пишите код сами.

2)Указание зависимостей с помощью атрибутов. Для свойств есть DependencyAttribute, для конструктора указывается InjectionConstructorAttribute, для метода InjectionMethodAttribute. Для параметров конструктора и injection-методов также можно указывать DependencyAttribute.
При навешивании DependencyAttribute на свойство или параметр можно указать имя зависимости.

3)Задание конфигурации в коде при добавлении элемента в контейнер.
Последним параметром метода RegisterType является массив InjectionMember. В этом массиве можно передать объекты типа InjectionProperty, InjectionConstructor и InjectionMethod чтобы указать с помощью каких членов класса проводить инъекцию.
При указании InjectionConstructor и InjectionMethod для каждого параметра можно указать конкретное значение или попросить контейнер резолвить нужный параметр.
Такой способ дает гораздо более многословен, чем все остальные способы, но дает гораздо большую гибкость. С помощью конфигурации в коде можно использовать IoC с классами, к исходникам которых нет доступа.

4)Задание конфигурации в XML.  Этот способ имеет смысл применять только если нужно изменять конфигурацию без  перекомпиляции  программы. Конфигурация в XML не позволяет описывать произвольные типы, поэтому обладает меньшей мощностью по сравнению с конфигурацией в коде.

Подробнее о возможностях конфигурирования Unity можно почитать по ссылкам
http://msdn.microsoft.com/en-us/library/dd203225.aspx
http://msdn.microsoft.com/en-us/library/dd203208.aspx
http://msdn.microsoft.com/en-us/library/dd203195.aspx
http://msdn.microsoft.com/en-us/library/dd203156.aspx
http://msdn.microsoft.com/en-us/library/dd203230.aspx

Overconfiguration или Темная сторона силы

Часто программисты, познакомившись с IoC-контейнерами и оценив их возможности декларативного конфигурирования, начинают использовать конфигурацию по любому поводу. Это приводит к тому что конфиги становятся монструозных размеров и абсолютно нечитаемые. При этом по коду программы абсолютно невозможно понять какой код когда выполняется. Любые изменения затрагивают не только код, но и конфигурацию, что может привести к проблемам при развертывании.

Поэтому при использовании любой технологии, которая может очень сильно конфигурироваться, предпочитайте пользоваться соглашениями (Convetions over Configuration) и размещайте конфигурацию как можно ближе к месту использования. Для этого используйте атрибуты и помещайте код конфигурирования в ту же сборку, где находятся конфигурируемые классы.



Управление временем жизни объектов в Unity

При регистрации класса или объекта в контейнере можно указать объект LifetimeManager, который будет управлять временем жизни экземпляров в контейнере.

Класс LifetimeManager очень простой, в нем всего три метода GetValue, SetValue и RemoveValue, причем последний не используется.
При помещении объекта в контейнер вызывается метод SetValue, а при необходимости получить объект вызывается GetValue и если он вернул null, то создается новый объект.

В библиотеку Microsoft.Practices.Unity входит несколько менеджеров.

TransientLifetimeManager – ничего не сохраняет, GetValue всегда возвращает null, поэтому объект создается каждый раз. Этот менеджер используется по-умолчанию при вызове RegisterType.

ContainerControlledLifetimeManager – сохраняет объект в локальной переменной. Поэтому объект живет столько же, сколько и контейнер. Этот (вернее другой, но с таким же поведением) менеджер используется по-умолчанию при вызове RegisterInstance.

ExternallyControlledLifetimeManager – сохраняет слабую ссылку (WeakReference) на объект. При использовании этого менеджера и вызове RegisterInstance сам вызывающий код должен управлять временем жизни объекта, помещенного в контейнер. Когда используется RegisterType этот менеджер будет выдавать уже существующий экземпляр объекта если он есть.

PerThreadLifetimeManager – сохраняет объекты в ThreadStatic словаре. Таким образом каждый поток в программе будет использовать свой набор объектов.

Для применения Unity в ASP.NET приложениях очень легко реализовать LifetimeManager, который сохраняет объект в контексте или в сессии.

Другие области применения LifetimeManager

В Unity нет возможности регистрации метода создания объектов, но это очень легко исправить с помощью своего LifetimeManager и пары extension-методов.

public class FactoryLifetimeManager<T>: LifetimeManager
{
    Func<T> _factoryMethod;
    LifetimeManager _baseManager;


                
            


Инъекция массивов в Unity

Unity умеет резолвить зависимости-массивы. Для такой зависимости контейнер возвращает объекты всех подходящих типов. Даже при разрешении зависимостей с указанием имени будут возвращены все подходящие типы.

Также этого Unity поддерживает разрешение обобщенных массивов.

Пример

Интерфейс и классы логгеров

public interface ILogger
{
    void Write(string message);
}


                
            


Использование generic-ов в Unity

Unity поддерживает работу с generic-типами. 
Можно в контейнер поместить обобщенный тип,  а потом запросить тип с конкретными параметрами.  Подробнее описано по ссылке http://msdn.microsoft.com/en-us/library/dd203156.aspx

Пример кода, использующего такую фичу.

Рассмотрим обобщенный класс репозитария для работы с данными

public interface IRepository<T>
{
    IQueryable<T> Items();
    void Save(T item);
    void Delete(T item);
}


Рефакторинг legacy кода для использования Unity

Представим себе код, который был написан без применения принципов IoC.
Например такой

public class AccountManager
{
    public void CreateAccount(string userName, string password)
    {
        var accountStore = new AccountStore();
        accountStore.AddNewAccount(userName, password);
    }


                
            


Используем IoC-контейнер Unity

Unity – IoC-контейнер от Microsoft, разработанный группой Patterns&Practicies. Найти его можно по адресу http://www.codeplex.com/unity. Также Unity включен в состав Enterprise Library.

Будет использоваться версия 1.2, последняя на данный момент.

Итак приступим.
Как завещал дядька Фаулер будем рассматривать использования контейнера на примере программы, работающей  с базой данных фильмов.

Чтобы использовать Unity в своей программе надо подключить сборки Microsoft.Practices.ObjectBuilder2 и Microsoft.Practices.Unity.

Нам надо написать класс, который позволяет искать фильмы по различным параметрам.

Предположим что фильмы описываются классом Movie

public class Movie
{
    public string Title { get; set; }
    public string Director { get; set; }
    public int Year { get; set; }
}


Введение в IoC

(Пост на RSDN)

Есть класс A и зависит от от класса B (использует его).

Например так:
public class A
{
   B b = new B();
   void foo()
   { 
      //используем b
   }
}