C# Language
의존성 주입
수색…
비고
의존성 주입에 대한 Wikipedia의 정의는 다음과 같습니다.
소프트웨어 엔지니어링에서 종속성 주입은 의존성 해결을위한 제어 반전을 구현하는 소프트웨어 설계 패턴입니다. 의존성은 사용할 수있는 객체입니다 (서비스). 인젝션 (injection)은 그것을 사용하는 의존 객체 (클라이언트)에게 의존성을 전달하는 것이다.
** 이 사이트에는 5 세 아동에게 의존성 주사를 설명하는 방법에 대한 답변이 있습니다. 존 먼츠 (John Munsch)가 제공 한 가장 높은 평가를받은 답은 (가상의) 5 살짜리 심문자를 대상으로 한 놀라운 비유를 제공합니다. 당신이 가서 냉장고에서 물건을 꺼낼 때 문제가 발생할 수 있습니다. 문을 열어두면 엄마 나 아빠가 원하지 않는 것을 얻을 수 있습니다. 우리가 가지고 있지 않거나 만료 된 무언가를 찾고있을 수도 있습니다. 네가해야 할 일은 "점심 먹고 마실 것이있어."라고 말하는 것입니다. 그러면 앉아서 먹을 때 뭔가를 갖도록 할 것입니다. 객체 지향 소프트웨어 개발 측면에서 이것이 의미하는 바는 다음과 같습니다. 공동 수업 (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 injection을 사용해야하는 이유는 무엇입니까? 우리는 우리 프로그램에서 다른 구성 요소와 다른 구성 요소를 분리하려고합니다. 예를 들어 다음과 같은 코드를 가진 AnimalController 클래스가 있습니다.
public class AnimalController()
{
private SantaAndHisReindeer _SantaAndHisReindeer = new SantaAndHisReindeer();
public AnimalController(){
Console.WriteLine("");
}
}
이 코드를 살펴보면 모든 것이 괜찮다고 생각하지만 이제 AnimalController는 _SantaAndHisReindeer 객체에 의존합니다. 자동으로 컨트롤러가 테스트에 좋지 않으며 코드 재사용 성이 매우 어려울 것입니다.
Depedency Injection과 인터페이스를 사용해야하는 이유에 대해 아주 잘 설명 합니다 .
Unity가 DI를 처리하기를 원한다면, 이것을 달성하는 길은 매우 간단합니다 :) NuGet (패키지 관리자)를 사용하면 코드에 대한 통합을 쉽게 가져올 수 있습니다.
Visual Studio Tools -> NuGet Package Manager -> 솔루션 패키지 관리 -> 검색 입력 단일체 -> 프로젝트 선택 -> 설치를 클릭하십시오.
이제 멋진 주석이있는 두 개의 파일이 생성됩니다.
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 -> 또한이 클래스가 ASP.NET MVC와 Unity를 통합한다고 말하는 멋진 주석이 있습니다.
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();
}
}
}