C# Language
Abhängigkeitsspritze
Suche…
Bemerkungen
Wikipedia-Definition der Abhängigkeitsinjektion ist:
Beim Software-Engineering ist Abhängigkeitsinjektion ein Software-Entwurfsmuster, das eine Inversion der Steuerung zur Auflösung von Abhängigkeiten implementiert. Eine Abhängigkeit ist ein Objekt, das verwendet werden kann (ein Dienst). Eine Injektion ist die Weitergabe einer Abhängigkeit an ein abhängiges Objekt (einen Client), das diese verwenden würde.
** Diese Website enthält eine Antwort auf die Frage Wie ist Abhängigkeitsinjektion für einen 5-jährigen Patienten zu erklären. Die am besten bewertete Antwort von John Munsch bietet eine überraschend genaue Analogie für den (imaginären) fünfjährigen Inquisitor: Wenn Sie sich selbst etwas aus dem Kühlschrank holen, können Sie Probleme verursachen. Sie könnten die Tür offen lassen, Sie könnten etwas bekommen, das Mama oder Papa nicht haben wollen. Vielleicht suchen Sie sogar nach etwas, das wir nicht haben oder das abgelaufen ist. Was Sie tun sollten, ist ein Bedürfnis: "Ich brauche etwas zu Mittag zu trinken" und dann sorgen wir dafür, dass Sie etwas haben, wenn Sie sich zum Essen setzen. Für die objektorientierte Softwareentwicklung bedeutet dies Folgendes: Zusammenarbeitende Klassen (die Fünfjährigen) sollten sich auf die Infrastruktur (die Eltern) verlassen, die sie zur Verfügung stellen
** Dieser Code verwendet MEF, um die DLL dynamisch zu laden und die Abhängigkeiten aufzulösen. Die ILogger-Abhängigkeit wird von MEF aufgelöst und in die Benutzerklasse eingefügt. Die Benutzerklasse erhält nie eine konkrete Implementierung von ILogger und hat keine Ahnung, welche Art von Logger sie verwendet. **
Abhängigkeitsinjektion mit 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);
}
}
}
Abhängigkeit Injection C # und ASP.NET mit Unity
Warum sollten wir in unserem Code die Depedenzinjektion verwenden? Wir möchten andere Komponenten von anderen Klassen unseres Programms entkoppeln. Zum Beispiel haben wir die Klasse AnimalController, die folgenden Code hat:
public class AnimalController()
{
private SantaAndHisReindeer _SantaAndHisReindeer = new SantaAndHisReindeer();
public AnimalController(){
Console.WriteLine("");
}
}
Wir betrachten diesen Code und denken, dass alles in Ordnung ist, aber jetzt ist unser AnimalController auf das Objekt _SantaAndHisReindeer angewiesen. Automatisch ist mein Controller schlecht zum Testen und die Wiederverwendbarkeit meines Codes wird sehr schwierig sein.
Sehr gute Erklärung , warum sollten wir Depedency Injection und Schnittstellen verwenden hier .
Wenn wir möchten, dass Unity mit DI umgeht, ist der Weg dafür sehr einfach :) Mit NuGet (Paketmanager) können wir Unity problemlos in unseren Code importieren.
in Visual Studio Tools -> NuGet Package Manager -> Verwalten von Paketen für Lösungen -> in der Eingabe-Eingabeeinheit schreiben -> Wählen Sie unser Projekt -> Klicken Sie auf Installieren
Nun werden zwei Dateien mit schönen Kommentaren erstellt.
im App-Data-Ordner UnityConfig.cs und UnityMvcActivator.cs
UnityConfig - In der RegisterTypes-Methode sehen wir den Typ, der in unsere Konstruktoren injiziert wird.
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 -> auch mit schönen Kommentaren, die besagen, dass diese Klasse Unity mit ASP.NET MVC integriert
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();
}
}
}
Jetzt können wir unseren Controller von der Klasse SantAndHisReindeer entkoppeln :)
public class AnimalController()
{
private readonly SantaAndHisReindeer _SantaAndHisReindeer;
public AnimalController(SantaAndHisReindeer SantaAndHisReindeer){
_SantAndHisReindeer = SantaAndHisReindeer;
}
}
Vor dem Ausführen unserer Anwendung müssen Sie noch eine letzte Maßnahme ausführen.
In Global.asax.cs müssen wir eine neue Zeile hinzufügen: UnityWebActivator.Start (), die startet, Unity konfiguriert und unsere Typen registriert.
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();
}
}
}