Cách thêm Dependency Injection (DI) bằng Unity MVC 4 trong lớp Non Controller
Vì vậy, tôi đang sử dụng Unity MVC-4 để đạt được Dependency Injection và nó hoạt động tốt với Controllercác lớp của tôi nhưng ngay sau khi tôi cố gắng đưa vào lớp không phải bộ điều khiển của mình, tôi nhận được NullReferenceExceptionvà tôi có thể thấy rằng các đối tượng được đưa vào của tôi không được khởi tạo bởi khuôn khổ . Tôi sẽ cung cấp cho bạn các lớp tương ứng mà tôi đang sử dụng:
Controller lớp (DI hoạt động):
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;
}
}
Và nếu tôi làm điều tương tự trong một phương thức không phải bộ điều khiển (DI không hoạt động ở đây), tôi nhận được 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.csLớp của tôi trông giống như:
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)
{
}
}
Nếu bạn thấy ở trên trong dòng container.RegisterType<IMyService , MyService>();, giao diện và cách triển khai cụ thể của nó nằm trong một mô-đun riêng biệt.
Và của tôi Global.asax.cslà:
protected void Application_Start()
{
Bootstrapper.Initialise();
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new OfflineActionFilter());
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Làm thế nào tôi có thể tiêm IMyServicetrong MyLogiclớp?
Trả lời
Sử dụng thuộc tính [InjectionConstructor] để cho Unity biết rằng MyLogiclớp phụ thuộc vào một đối tượng sẽ được đưa vào trong hàm tạo:
[InjectionConstructor]
public MyLogic(IMyService myService)
{
_myService = myService;
}
Trên thực tế, [InjectionConstructor]nó được khuyến khích sử dụng khi lớp được đưa vào chứa nhiều hơn một hàm tạo. Do đó, thuộc tính được sử dụng để giải quyết định hướng. Đó chỉ là giả thuyết của tôi tại sao Unitykhông thể giải quyết loại bắt buộc, vì mã câu hỏi không chứa tất cả các phần của mã. Nhưng trong mã kiểm tra bên dưới [InjectionConstructor]thuộc tính không cần thiết, vì chỉ có một hàm tạo được khai báo.
Đây là mã thử nghiệm.
Các IMyServiceđịnh nghĩa giao diện:
public interface IMyService
{
string GetMyStringFromDLL();
}
Các ILogicđịnh nghĩa giao diện:
public interface IMyLogic
{
string GetMyString();
}
Việc MyLogicthực hiện:
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;
}
}
Việc MyServicethực hiện:
public class MyService : IMyService
{
public string GetMyStringFromDLL()
{
return "MyService.GetMyStringFromDLL() is called.";
}
}
Khởi Bootstrappertạo:
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;
}
}
Việc Homethực hiện bộ điều khiển:
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} );
}
}
Và cuối cùng khi phương thức hành động mặc định của Homebộ điều khiển được thực thi, hai dòng sau được hiển thị:
MyService.GetMyStringFromDLL() is called.
MyLogic.GetMyString() -> MyService.GetMyStringFromDLL() is called.
Tôi chưa làm việc với Unity kể từ lần cuối cùng tôi thực hiện một số công việc trên NopCommerce V1.90, tuy nhiên, tôi nhớ rằng bất kỳ thứ gì bạn đăng ký trong vùng chứa của mình sẽ trở lại nếu bạn sử dụng Resolve trên một phiên bản triển khai IUnityResolver.
Vì vậy, về cơ bản, bạn đã đăng ký IMyService, nhưng bạn cũng phải đăng ký IMyLogic - sau đó thay vì thực hiện "var logic = new MyLogic ();", bạn sẽ thực hiện "var logic = Resolutionver.Resolve (typeof (IMyLogic)); " và sau đó các thông số được tiêm của bạn sẽ được giải quyết theo bộ tiêm phụ thuộc (hoặc bạn sẽ nhận được các lỗi thích hợp nếu chúng bị thiếu).