Sök…


Anmärkningar

Wikipedia definition av beroende injektion är:

Inom mjukvaruteknik är beroendeinjicering ett mönster för mjukvarudesign som implementerar inversion av kontroll för att lösa beroenden. Ett beroende är ett objekt som kan användas (en tjänst). En injektion är överföring av ett beroende till ett beroende objekt (en klient) som skulle använda det.

** Den här webbplatsen innehåller ett svar på frågan Hur man förklarar beroende injektion till en 5-åring. Det mest betygsatta svaret, tillhandahållet av John Munsch, ger en förvånansvärt noggrann analogi riktad till den (imaginära) fem år gamla inkvisitorn: När du går ut ur kylen för dig själv kan du orsaka problem. Du kan lämna dörren öppen, du kan få något mamma eller pappa inte vill att du ska ha. Du kanske till och med letar efter något vi inte ens har eller som har gått ut. Det du borde göra är att säga ett behov, ”Jag behöver något att dricka med lunch,” och sedan kommer vi att se till att du har något när du sätter dig och äter. Vad detta innebär när det gäller objektorienterad mjukvaruutveckling är detta: samverkande klasser (femåringarna) bör lita på infrastrukturen (föräldrarna) för att tillhandahålla

** Den här koden använder MEF för att dynamiskt ladda dll och lösa beroenden. ILoggerberoende löses av MEF och injiceras i användarklassen. Användarklassen får aldrig konkret implementering av ILogger och har ingen aning om vilken eller vilken typ av logger den använder. **

Beroende injektion med 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);
        }
    } 
}

Beroende på injektion C # och ASP.NET med enhet

Först varför vi ska använda depedency-injektion i vår kod? Vi vill avkoppla andra komponenter från andra klasser i vårt program. Vi har till exempel klass AnimalController som har kod som denna:

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

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

Vi tittar på den här koden och vi tycker att allt är ok, men nu är vår AnimalController beroende av objektet _SantaAndHisReindeer. Automatisk min Controller är dålig att testa och återanvändbarhet av min kod kommer att vara mycket svårt.

Mycket bra förklaring till varför vi ska använda Depedency Injection och gränssnitt här .

Om vi vill att Unity ska hantera DI är vägen att uppnå detta väldigt enkelt :) Med NuGet (paketansvarig) kan vi enkelt importera enhet till vår kod.

i Visual Studio Tools -> NuGet Package Manager -> Hantera paket för lösning -> i sökinmatning skriva enhet -> välj vårt projekt-> klicka på installera

Nu skapas två filer med fina kommentarer.

i mappen App-data UnityConfig.cs och UnityMvcActivator.cs

UnityConfig - i RegisterTypes-metoden kan vi se typ som kommer att injiceras i våra konstruktörer.

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 -> också med fina kommentarer som säger att den här klassen integrerar Unity med 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 kan vi avkoppla vår controller från klass SantAndHisReindeer :)

 public class AnimalController()
    {
        private readonly SantaAndHisReindeer _SantaAndHisReindeer;

        public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){

                _SantAndHisReindeer = SantaAndHisReindeer;
        }
    }

Det är en sista sak vi måste göra innan vi kör vår ansökan.

I Global.asax.cs måste vi lägga till en ny rad: UnityWebActivator.Start () som startar, konfigurerar Unity och registrerar våra typer.

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
Licensierat under CC BY-SA 3.0
Inte anslutet till Stack Overflow