Инверсия управления и внедрение зависимостей в .NET Framework - PullRequest
13 голосов
/ 20 июля 2010

Существует ли какой-либо конкретный пример / экземпляр DI, применяемый в качестве архитектурного принципа или шаблона проектирования в самой .NET Framework ?Какой-либо (или многие) из типов в framework / BCL соответствуют IoC?

Имена типов и краткая иллюстрация / объяснение, основанное на C #, было бы здорово!

Это бы компенсировало необходимость использования принципа DI-инфузии в качестве передового опыта ... так как он взят из самой базовой структуры.

Повторюсь, я не ищу IoC /Рамки DI НО для IoC / DI IN Каркас.

РЕДАКТИРОВАТЬ: Просто хотел получить больше экземпляров / примеров ... отсюда и награда!

Ответы [ 6 ]

16 голосов
/ 26 июля 2010

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

Внедрение в конструктор

В BCL не так много примеров внедрения в конструктор.Лучшими кандидатами являются

  • System.IO.StreamWriter
  • System.IO.StreamReader

Внедрение свойства

  • System.ComponentModel.IComponent.Site

Мы также видим изменение в WorkflowRuntime.AddService Workflow Foundation и связанных с ним методах, хотя вы можете утверждать, что это ближе к внедрению метода.

Внедрение метода

  • System.ComponentModel.Design.IDesigner.Initialize
  • System.ComponentModel.TypeConverter (многие методы принимают ITypeDescriptorContext)
  • System.Web.Mvc.IModelBinder.BindModel (из ASP.NET MVC)

Окружающий контекст

  • System.Threading.Thread.CurrentPrincipal
  • System.Threading.Thread.CurrentCulture
  • System.Threading.Thread.CurrentUICulture
  • System.Diagnostics.Trace.Listeners

Я взял эти примеры из моей будущей книги .

12 голосов
/ 20 июля 2010

Как StreamReader, так и StreamWriter можно рассматривать как примеры IoC / DI.

Каждый позволяет вам вводить различные объекты Stream (или одну из его производных) для чтения / записи соответственно.

FileInfo fi = new FileInfo(@"C:\MyFile.dat");
StreamWriter sw = new StreamWriter(fi.Open());

Или:

MemoryStream ms = new MemoryStream();
StreamWriter sw = new StreamWriter(ms);

Позволят ли оба:

sw.Write("Hello world!");

Точно так же, независимо от того, какой поток вы вводили при вызове конструктора.

5 голосов
/ 21 июля 2010

Конечно - интерфейс IServiceProvider является частью Framework с 1.0.Это не DI, как это обычно обсуждается здесь (с использованием «ядра»), но это IoC, использующий шаблон Service Locator.

Если вы покопаетесь в любом из кодов Windows Forms Designer, выувидим, что он щедро усыпан такими строками, как эта:

IDesignerOptionService service = 
    (IDesignerOptionService)this.GetService(typeof(IDesignerOptionService));

Если вы работаете с Компонентом , то вы получите доступ к этому через свойство Site ,Это довольно распространенное и практически необходимое знание при создании пользовательских элементов управления.

Это расположение службы, пример из учебника.У вас есть общий IServiceProvider, который раздает абстрактные услуги, которые вы запрашиваете по типу службы.Если вы когда-нибудь захотите создать нестандартные дизайнеры - смарт-теги и т. Д. - вам нужно знать все это.Это похоже и на ASP.NET.


PS Пожалуйста, не используйте IServiceProvider в новом коде.Это очень старый, не универсальный интерфейс.Если вы создаете многократно используемые библиотеки, для работы которых требуется контейнер IoC, вам следует использовать вместо этого Common Service Locator .Но даже не используйте , , если только вы абсолютно не требуете, чтобы ваша библиотека была независимой от библиотеки DI, используемой на уровне приложения;большинство специфичных для реализации контейнеров / ядер предлагают гораздо более богатые API, которые вы пропустите, если прибегнете к CSL.

4 голосов
/ 21 июля 2010

Это пример того, как вы можете создать System.ComponentModel.Composition.Hosting.CompositionContainer в .NET 4:

var exeCatalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
var dircatalog = new DirectoryCatalog(".");
var aggregateCatalog = new AggregateCatalog(exeCatalog, dirCatalog);
var exportProvider = new CatalogExportProvider(aggregateCatalog);
var container = new CompositionContainer(exportProvider);

Это пример внедрения зависимости через аргументы конструктора. Поскольку использовался шаблон внедрения зависимостей, эти классы очень расширяемы: вы можете написать свою собственную реализацию ComposablePartCatalog и передать ее конструктору поставщика экспорта. Или вы можете обойти всю концепцию каталогов деталей и написать собственную реализацию ExportProvider.

(Между прочим, CompostionContainer сам по себе является частью инфраструктуры IoC, но это не главное в этом примере.)

3 голосов
/ 26 июля 2010

.NET, особенно в веб-контексте, предлагает провайдерам определять альтернативные реализации компонентов инфраструктуры. Фреймворк определяет абстрактный базовый класс, определяет одну или две конкретные реализации поверх него и позволяет пользователям предоставлять свои собственные реализации там, где это необходимо.

После определения пользователь не контролирует жизненный цикл своей реализации. Инфраструктура вступает во владение и управляет созданием, настройкой и утилизацией.

Начните с System.Configuration.Provider.ProviderBase .

.NET классы, которые реализуют ProviderBase:

  • System.Configuration.ProtectedConfigurationProvider - шифрование и дешифрование данных защищенной конфигурации
    • System.Configuration.DpapiProtectedConfigurationProvider (бетон)
    • System.Configuration.RsaProtectedConfigurationProvider (бетон)
  • System.Configuration.SettingsProvider - пользовательские настройки в архитектуре настроек приложения
    • System.Configuration.LocalFileSettingsProvider (бетон)
    • System.Web.Profile.ProfileProvider
      • System.Web.Profile.SqlProfileProvider (бетон)
  • System.Web.Management.WebEventProvider - настроить обработку событий работоспособности ASP.NET
    • System.Web.Management.BufferedWebEventProvider
      • System.Web.Management.MailWebEventProvider
        • System.Web.Management.SimpleMailWebEventProvider (бетон)
        • System.Web.Management.TemplatedMailWebEventProvider (конкретный)
      • System.Web.Management.SqlWebEventProvider (бетон)
    • System.Web.Management.EventLogWebEventProvider (бетон)
    • System.Web.Management.IisTraceWebEventProvider (бетон)
    • System.Web.Management.TraceWebEventProvider (бетон)
    • System.Web.Management.WmiWebEventProvider (бетон)
  • System.Web.Security.MembershipProvider - пользовательское членство для служб членства
    • System.Web.Security.ActiveDirectoryMembershipProvider (бетон)
    • System.Web.Security.SqlMembershipProvider (бетон)
  • System.Web.Security.RoleProvider - настраиваемое управление ролями для служб управления ролями
    • System.Web.Security.AuthorizationStoreRoleProvider (бетон)
    • System.Web.Security.SqlRoleProvider (бетон)
    • System.Web.Security.WindowsTokenRoleProvider (бетон)
  • System.Web.SessionState.SessionStateStoreProviderBase - хранилища данных о состоянии сеанса
    • System.Web.SessionState.InProcSessionStateStore (concrete)
    • System.Web.SessionState.OutOfProcSessionStateStore (concrete)
    • System.Web.SessionState.SqlSessionStateStore (concrete)
  • System.Web.SiteMapProvider - пользовательское постоянное хранилище данных SiteMap
    • System.Web.StaticSiteMapProvider
      • System.Web.XmlSiteMapProvider (бетон)
  • System.Web.UI.WebControls.WebParts.PersonalizationProvider - загружает и сохраняет данные персонализации от имени экземпляра WebPartPersonalization
    • System.Web.UI.WebControls.WebParts.SqlPersonalizationProvider (конкретный)

Примеры:

2 голосов
/ 21 июля 2010

В настоящее время я читаю книгу Роя Ошерова Искусство модульного тестирования .Он упоминает метод под названием Извлечение и перегрузка (то есть внедрение зависимости в класс путем переопределения виртуального метода, который отвечает за возвращение зависимости).

Я думаю, что я сталкивался с различными примерами этой техники, например:

  • Настройка типа ADO.NET DataTable: Если вы унаследовали от DataTable, у вас есть возможность переопределить различные методы, такие как GetRowType(), CreateInstance() и другие.

  • Настройка конструкторов операций Workflow Foundation(в .NET 3.5) Я не помню точный класс, но я думаю, что если вы хотите создавать индивидуальные дизайны действий, вы извлекаете новые классы из существующих, и шаблон во многом такой же;вы переопределяете виртуальный метод, который позволяет вам возвращать вашу пользовательскую зависимость в платформу.

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