Ricerca…


Osservazioni

La definizione di Wikipedia di iniezione di dipendenza è:

Nell'ingegneria del software, l'iniezione di dipendenza è un modello di progettazione software che implementa l'inversione del controllo per la risoluzione delle dipendenze. Una dipendenza è un oggetto che può essere utilizzato (un servizio). Un'iniezione è il passaggio di una dipendenza a un oggetto dipendente (un client) che lo userebbe.

** Questo sito offre una risposta alla domanda Come spiegare l'iniezione di dipendenza a un bambino di 5 anni. La risposta più votata, fornita da John Munsch, fornisce un'analogia sorprendentemente precisa rivolta al (immaginario) inquisitore quinquennale: quando vai a prendere le cose dal frigorifero per conto tuo, puoi causare problemi. Potresti lasciare la porta aperta, potresti ottenere qualcosa che mamma o papà non vogliono che tu abbia. Potresti anche cercare qualcosa che non abbiamo nemmeno o che è scaduto. Quello che dovresti fare è affermare un bisogno, "Ho bisogno di qualcosa da bere a pranzo", e poi ci assicureremo che tu abbia qualcosa quando ti siedi per mangiare. Cosa significa in termini di sviluppo di software orientato agli oggetti è questo: le classi collaborative (i bambini di cinque anni) dovrebbero fare affidamento sull'infrastruttura (i genitori) per fornire

** Questo codice utilizza MEF per caricare dinamicamente la dll e risolvere le dipendenze. La dipendenza di ILogger è risolta da MEF e iniettata nella classe utente. La classe utente non riceve mai l'implementazione concreta di ILogger e non ha idea di quale tipo di registratore utilizzi. **

Iniezione delle dipendenze con 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);
        }
    } 
}

Dipendenza Injection C # e ASP.NET con Unity

Innanzitutto perché dovremmo usare l'iniezione di depedency nel nostro codice? Vogliamo disaccoppiare altri componenti da altre classi nel nostro programma. Ad esempio abbiamo AnimalController di classe che hanno un codice come questo:

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

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

Guardiamo questo codice e pensiamo che tutto sia a posto, ma ora il nostro AnimalController dipende dall'oggetto _SantaAndHisReindeer. Automaticamente il mio controller non è adatto ai test e la riusabilità del mio codice sarà molto difficile.

Ottima spiegazione del motivo per cui dovremmo usare Injection e interfacce qui .

Se vogliamo che Unity gestisca DI, la strada per raggiungerla è molto semplice :) Con NuGet (gestore pacchetti) possiamo facilmente importare unità nel nostro codice.

in Visual Studio Tools -> NuGet Package Manager -> Gestisci pacchetti per soluzione -> in input di ricerca scrivi unità -> scegli il nostro progetto-> fai clic su Installa

Ora verranno creati due file con commenti interessanti.

nella cartella App-Data UnityConfig.cs e UnityMvcActivator.cs

UnityConfig - nel metodo RegisterTypes, possiamo vedere il tipo che verrà inserito nei nostri costruttori.

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 -> anche con dei bei commenti che dicono che questa classe integra Unity con 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();
    }
}
}

Ora possiamo disaccoppiare il nostro controller dalla classe SantAndHisReindeer :)

 public class AnimalController()
    {
        private readonly SantaAndHisReindeer _SantaAndHisReindeer;

        public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){

                _SantAndHisReindeer = SantaAndHisReindeer;
        }
    }

C'è un'ultima cosa che dobbiamo fare prima di eseguire la nostra applicazione.

In Global.asax.cs dobbiamo aggiungere una nuova riga: UnityWebActivator.Start () che verrà avviato, configurare Unity e registrare i nostri tipi.

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
Autorizzato sotto CC BY-SA 3.0
Non affiliato con Stack Overflow