비 컨트롤러 클래스에서 Unity MVC 4를 사용하여 DI (Dependency Injection)를 추가하는 방법
따라서 종속성 주입을 달성하기 위해 Unity MVC-4를 사용하고 있으며 Controller
클래스 와 잘 작동 하지만 컨트롤러가 아닌 클래스에 주입을 시도하자마자 NullReferenceException
주입 된 객체가 프레임 워크에 의해 초기화되지 않음을 알 수 있습니다. . 내가 사용하는 해당 클래스를 제공합니다.
Controller
수업 (DI 작품) :
public class HomeController : Controller
{
IMyService _myService;
#region CTOR
public HomeController(IMyService myService)
{
_myService = myService;
}
#endregion
public string GetMyString()
{
string mystring=string.Empty;
try
{
mystring = _myService.GetMyStringFromDLL();
}
catch (Exception ex)
{
StringBuilder str = new StringBuilder();
str.AppendLine("Exception in method GetMyString, Error msg: " + ex.Message);
WriteLog(sb);
}
return mystring;
}
}
비 컨트롤러 메서드에서 동일한 작업을 수행하면 (DI는 여기서 작동하지 않음) NullReferenceException
다음을 얻습니다 .
public inteface IMyLogic
{
string GetMyString();
}
public class MyLogic: IMyLogic
{
IMyService _myService;
#region CTOR
public MyLogic(IMyService myService)
{
_myService = myService;
}
#endregion
public string GetMyString()
{
string mystring=string.Empty;
try
{
mystring = _myService.GetMyStringFromDLL(); //Getting NullReferenceException here
}
catch (Exception ex)
{
StringBuilder str = new StringBuilder();
str.AppendLine("Exception in method GetMyString, Error msg: " + ex.Message);
WriteLog(sb);
}
return mystring;
}
}
내 BootStrapper.cs
수업은 다음과 같습니다.
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = BuildUnityContainer();
container.RegisterType<IMyService , MyService>();
container.RegisterType<IMyLogic, MyLogic>(new HierarchicalLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
}
public static void RegisterTypes(IUnityContainer container)
{
}
}
위의 행 container.RegisterType<IMyService , MyService>();
을 보면 인터페이스와 구체적인 구현이 별도의 모듈에있는 것입니다.
그리고 내 Global.asax.cs
:
protected void Application_Start()
{
Bootstrapper.Initialise();
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new OfflineActionFilter());
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
어떻게 삽입 할 수 IMyService
에서 MyLogic
클래스?
답변
[InjectionConstructor] 속성을 사용 하여 Unity에 MyLogic
클래스가 생성자에 삽입 될 객체에 종속되어 있음을 알립니다 .
[InjectionConstructor]
public MyLogic(IMyService myService)
{
_myService = myService;
}
실제로 [InjectionConstructor]
주입 된 클래스에 둘 이상의 생성자가 포함 된 경우 사용 하는 것이 좋습니다. 따라서이 특성은 명확성을 해결하는 데 사용됩니다. Unity
질문 코드에 코드의 일부가 포함되어 있지 않기 때문에 필요한 유형을 해결할 수없는 이유는 내 가설이었습니다 . 그러나 아래의 테스트 코드에서는 [InjectionConstructor]
생성자가 하나만 선언 되었기 때문에 속성이 필요하지 않습니다.
여기에 테스트 코드가 있습니다.
IMyService
인터페이스 정의 :
public interface IMyService
{
string GetMyStringFromDLL();
}
ILogic
인터페이스 정의 :
public interface IMyLogic
{
string GetMyString();
}
MyLogic
구현 :
public class MyLogic : IMyLogic
{
IMyService _myService;
public MyLogic(IMyService myService)
{
_myService = myService;
}
public string GetMyString()
{
var mystring = string.Empty;
try
{
mystring = "MyLogic.GetMyString() -> " + _myService.GetMyStringFromDLL();
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine("Exception in method MyLogic.GetMyString(): " + ex.Message);
}
return mystring;
}
}
MyService
구현 :
public class MyService : IMyService
{
public string GetMyStringFromDLL()
{
return "MyService.GetMyStringFromDLL() is called.";
}
}
Bootstrapper
초기화 :
public static class Bootstrapper
{
public static IUnityContainer Initialise()
{
var container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
container.RegisterType<IMyLogic, MyLogic>(new HierarchicalLifetimeManager());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
return container;
}
}
Home
컨트롤러 구현 :
public class HomeController : Controller
{
private readonly IMyService _myService;
private readonly IMyLogic _myLogic;
#region CTOR
public HomeController(IMyService myService, IMyLogic myLogic)
{
_myService = myService;
_myLogic = myLogic;
}
#endregion
public ActionResult Index()
{
// Obtaining string directly from the IMyService
var sService = _myService.GetMyStringFromDLL();
// Obtaining string through the IMyLogic
var sLogic = _myLogic.GetMyString();
return View(new List<string>() { sService, sLogic} );
}
}
마지막으로 Home
컨트롤러 의 기본 동작 방법이 실행되면 다음 두 줄이 표시됩니다.
MyService.GetMyStringFromDLL() is called.
MyLogic.GetMyString() -> MyService.GetMyStringFromDLL() is called.
마지막으로 NopCommerce V1.90에서 작업 한 이후로 Unity와 함께 작업 한 적이 없지만 IUnityResolver를 구현하는 인스턴스에서 Resolve를 사용하면 컨테이너에 등록한 모든 항목이 다시 표시된다는 것을 기억합니다.
따라서 기본적으로 IMyService를 등록했지만 IMyLogic도 등록해야합니다. "var logic = new MyLogic ();"대신 "var logic = resolver.Resolve (typeof (IMyLogic)); " 그런 다음 주입 된 매개 변수가 종속성 주입기에 따라 해결됩니다 (또는 누락 된 경우 적절한 오류가 발생 함).