Zoeken…


Opmerkingen

Wikipedia definitie van afhankelijkheid injectie is:

In software engineering is afhankelijkheidsinjectie een software-ontwerppatroon dat inversie van controle implementeert voor het oplossen van afhankelijkheden. Een afhankelijkheid is een object dat kan worden gebruikt (een service). Een injectie is het doorgeven van een afhankelijkheid aan een afhankelijk object (een client) dat het zou gebruiken.

** Deze site biedt een antwoord op de vraag Hoe een afhankelijkheidsinjectie uit te leggen aan een 5-jarige. Het meest gewaardeerde antwoord van John Munsch biedt een verrassend nauwkeurige analogie gericht op de (denkbeeldige) vijf jaar oude onderzoeker: als je dingen uit de koelkast haalt, kun je problemen veroorzaken. Misschien laat je de deur open, krijg je misschien iets dat mama of papa niet wil. Misschien zoekt u zelfs naar iets dat we niet eens hebben of dat is verlopen. Wat je zou moeten doen, is een behoefte vermelden: "Ik heb iets nodig om tijdens de lunch te drinken", en dan zullen we ervoor zorgen dat je iets hebt als je gaat zitten om te eten. Wat dit betekent voor objectgeoriënteerde softwareontwikkeling is dit: samenwerkende klassen (de vijfjarigen) moeten vertrouwen op de infrastructuur (de ouders) om

** Deze code gebruikt MEF om de DLL dynamisch te laden en de afhankelijkheden op te lossen. ILogger-afhankelijkheid wordt opgelost door MEF en geïnjecteerd in de gebruikersklasse. Gebruikersklasse ontvangt nooit Concrete implementatie van ILogger en heeft geen idee van wat of welk type logger het gebruikt. **

Afhankelijkheid injectie met behulp van 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);
        }
    } 
}

Afhankelijkheid Injectie C # en ASP.NET met Unity

Eerst waarom we depedency-injectie in onze code zouden moeten gebruiken? We willen andere componenten loskoppelen van andere klassen in ons programma. We hebben bijvoorbeeld de klasse AnimalController met een code als deze:

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

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

We kijken naar deze code en denken dat alles in orde is, maar nu is onze AnimalController afhankelijk van object _SantaAndHisReindeer. Mijn controller is automatisch slecht voor het testen en herbruikbaarheid van mijn code zal erg moeilijk zijn.

Zeer goede verklaring waarom we Depedency Injection en interfaces hier zouden moeten gebruiken.

Als we willen dat Unity DI afhandelt, is de weg om dit te bereiken heel eenvoudig :) Met NuGet (pakketbeheerder) kunnen we eenvoudig eenheid in onze code importeren.

in Visual Studio Tools -> NuGet Pakketbeheer -> Pakketten beheren voor oplossing -> in zoekinvoer schrijfeenheid -> kies ons project-> klik op installeren

Nu worden twee bestanden met leuke opmerkingen gemaakt.

in de map App-Data UnityConfig.cs en UnityMvcActivator.cs

UnityConfig - in de RegisterTypes-methode zien we het type dat in onze constructeurs wordt geïnjecteerd.

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 -> ook met leuke opmerkingen die zeggen dat deze klasse Unity integreert met 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();
    }
}
}

Nu kunnen we onze controller loskoppelen van klasse SantAndHisReindeer :)

 public class AnimalController()
    {
        private readonly SantaAndHisReindeer _SantaAndHisReindeer;

        public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){

                _SantAndHisReindeer = SantaAndHisReindeer;
        }
    }

Er is nog een laatste ding dat we moeten doen voordat onze applicatie wordt uitgevoerd.

In Global.asax.cs moeten we een nieuwe regel toevoegen: UnityWebActivator.Start () die start, Unity configureert en onze typen registreert.

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
Licentie onder CC BY-SA 3.0
Niet aangesloten bij Stack Overflow