Поиск…


замечания

Википедия: определение инъекции зависимостей:

В программной инженерии инъекция зависимостей представляет собой шаблон разработки программного обеспечения, который реализует инверсию управления для разрешения зависимостей. Зависимость - это объект, который может использоваться (услуга). Инъекция - это передача зависимости зависимому объекту (клиенту), который будет использовать его.

** На этом сайте есть ответ на вопрос. Как объяснить инъекцию зависимостей 5-летнему ребенку. Самый высоко оцененный ответ, предоставленный Джоном Муншем, дает удивительно точную аналогию, нацеленную на (воображаемого) пятилетнего инквизитора: когда вы идете и извлекаете вещи из холодильника для себя, вы можете создавать проблемы. Вы можете оставить дверь открытой, вы можете получить то, что мама или папа не хотят, чтобы вы имели. Возможно, вы даже ищете что-то, чего у нас нет или которое истекло. То, что вы должны делать, это заявить о необходимости: «Мне нужно что-нибудь выпить с обедом», а затем мы обязательно удостовериться, что у вас есть что-то, когда вы садитесь, чтобы поесть. То, что это означает с точки зрения объектно-ориентированного развития программного обеспечения, таково: сотрудничающие классы (пятилетние) должны полагаться на инфраструктуру (родителей), чтобы обеспечить

** Этот код использует MEF для динамической загрузки DLL и разрешения зависимостей. Зависимость ILogger разрешается с помощью MEF и вводится в класс пользователя. Пользовательский класс никогда не получает конкретную реализацию ILogger и не знает, какой или какой тип регистратора он использует. **

Инъекция с использованием MEF

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

[Export(typeof(ILogger))]
[ExportMetadata("Name", "Console")]  
public class ConsoleLogger:ILogger
{
    public void Log(string message)
    {
        Console.WriteLine(message);
    }
}

[Export(typeof(ILogger))]
[ExportMetadata("Name", "File")]  
public class FileLogger:ILogger
{
    public void Log(string message)
    {
        //Write the message to file
    }
}

public class User
{  
    private readonly ILogger logger;
    public User(ILogger logger)   
    {
        this.logger = logger;
    }
    public void LogUser(string message)
    {
        logger.Log(message)  ;
    }
}

public interface ILoggerMetaData
{
    string Name { get; }
}

internal class Program
{
    private CompositionContainer _container;
    
    [ImportMany]
    private IEnumerable<Lazy<ILogger, ILoggerMetaData>> _loggers;
    
    private static void Main()
    {            
        ComposeLoggers();
        Lazy<ILogger, ILoggerMetaData> loggerNameAndLoggerMapping = _ loggers.First((n) => ((n.Metadata.Name.ToUpper() =="Console"));
        ILogger logger= loggerNameAndLoggerMapping.Value
        var user = new User(logger);
        user.LogUser("user name");
    }
    
    private void ComposeLoggers()
    {
        //An aggregate catalog that combines multiple catalogs
        var catalog = new AggregateCatalog();
        string loggersDllDirectory =Path.Combine(Utilities.GetApplicationDirectory(), "Loggers");
        if (!Directory.Exists(loggersDllDirectory ))
        {
            Directory.CreateDirectory(loggersDllDirectory );
        }
        //Adds all the parts found in the same assembly as the PluginManager class
        catalog.Catalogs.Add(new AssemblyCatalog(typeof(Program).Assembly));
        catalog.Catalogs.Add(new DirectoryCatalog(loggersDllDirectory ));
        
        //Create the CompositionContainer with the parts in the catalog
        _container = new CompositionContainer(catalog);
        
        //Fill the imports of this object
        try
        {
            this._container.ComposeParts(this);
        }
        catch (CompositionException compositionException)
        {
            throw new CompositionException(compositionException.Message);
        }
    } 
}

Инъекция зависимостей C # и ASP.NET с Unity

Во-первых, почему мы должны использовать инъекцию depedency в нашем коде? Мы хотим отделить другие компоненты от других классов нашей программы. Например, у нас есть класс AnimalController, который имеет такой код:

public class AnimalController()
{
    private SantaAndHisReindeer _SantaAndHisReindeer = new SantaAndHisReindeer();

    public AnimalController(){
            Console.WriteLine("");
    }
}

Мы смотрим на этот код, и мы думаем, что все в порядке, но теперь наш AnimalController зависит от объекта _SantaAndHisReindeer. Автоматически мой контроллер плохо тестирует и повторное использование моего кода будет очень тяжелым.

Очень хорошее объяснение, почему мы должны использовать Depedency Injection и интерфейсы здесь .

Если мы хотим, чтобы Unity обрабатывала DI, дорога для достижения этого очень проста :) С NuGet (менеджер пакетов) мы можем легко импортировать единство в наш код.

в Visual Studio Tools -> Диспетчер пакетов NuGet -> Управление пакетами для решения -> в поле ввода ввода для ввода единства -> выберите наш проект-> нажмите кнопку установки

Теперь будут созданы два файла с хорошими комментариями.

в папке App-Data UnityConfig.cs и UnityMvcActivator.cs

UnityConfig - в методе RegisterTypes мы можем видеть тип, который будет встраиваться в наши конструкторы.

namespace Vegan.WebUi.App_Start
{

public class UnityConfig
{
    #region Unity Container
    private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
    {
        var container = new UnityContainer();
        RegisterTypes(container);
        return container;
    });

    /// <summary>
    /// Gets the configured Unity container.
    /// </summary>
    public static IUnityContainer GetConfiguredContainer()
    {
        return container.Value;
    }
    #endregion

    /// <summary>Registers the type mappings with the Unity container.</summary>
    /// <param name="container">The unity container to configure.</param>
    /// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to 
    /// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
    public static void RegisterTypes(IUnityContainer container)
    {
        // NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
        // container.LoadConfiguration();

        // TODO: Register your types here
        // container.RegisterType<IProductRepository, ProductRepository>();

        container.RegisterType<ISanta, SantaAndHisReindeer>();
        
     }
 }
}

UnityMvcActivator -> также с хорошими комментариями, которые говорят, что этот класс объединяет Unity с ASP.NET MVC

using System.Linq;
using System.Web.Mvc;
using Microsoft.Practices.Unity.Mvc;

[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(Vegan.WebUi.App_Start.UnityWebActivator), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(Vegan.WebUi.App_Start.UnityWebActivator), "Shutdown")]
    
namespace Vegan.WebUi.App_Start
{
/// <summary>Provides the bootstrapping for integrating Unity with ASP.NET MVC.</summary>
public static class UnityWebActivator
{
    /// <summary>Integrates Unity when the application starts.</summary>
    public static void Start() 
    {
        var container = UnityConfig.GetConfiguredContainer();

        FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
        FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));

        DependencyResolver.SetResolver(new UnityDependencyResolver(container));

        // TODO: Uncomment if you want to use PerRequestLifetimeManager
        // Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
    }

    /// <summary>Disposes the Unity container when the application is shut down.</summary>
    public static void Shutdown()
    {
        var container = UnityConfig.GetConfiguredContainer();
        container.Dispose();
    }
}
}

Теперь мы можем отделить наш контроллер от класса SantAndHisReindeer :)

 public class AnimalController()
    {
        private readonly SantaAndHisReindeer _SantaAndHisReindeer;

        public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){

                _SantAndHisReindeer = SantaAndHisReindeer;
        }
    }

Перед тем, как запустить наше приложение, мы должны сделать все возможное.

В Global.asax.cs мы должны добавить новую строку: UnityWebActivator.Start (), которая запустится, настроит Unity и зарегистрирует наши типы.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using System.Web.Optimization;
using System.Web.Routing;
using Vegan.WebUi.App_Start;

namespace Vegan.WebUi
{
    public class MvcApplication : System.Web.HttpApplication
    {
        protected void Application_Start()
        {
            AreaRegistration.RegisterAllAreas();
            FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
            RouteConfig.RegisterRoutes(RouteTable.Routes);
            BundleConfig.RegisterBundles(BundleTable.Bundles);
            UnityWebActivator.Start();
        }
    }
}


Modified text is an extract of the original Stack Overflow Documentation
Лицензировано согласно CC BY-SA 3.0
Не связан с Stack Overflow