Denetleyici Olmayan Sınıfta Unity MVC 4 kullanılarak Bağımlılık Enjeksiyonu (DI) nasıl eklenir
Bu yüzden, Bağımlılık Enjeksiyonu elde etmek için Unity MVC-4 kullanıyorum ve Controllersınıflarımla harika çalışıyor, ancak denetleyici olmayan sınıfıma enjekte etmeye çalıştığım anda, enjekte NullReferenceExceptionedilen nesnelerimin çerçeve tarafından başlatılmadığını görüyorum. . Size kullandığım ilgili sınıfları vereceğim:
Controller sınıf (DI çalışmaları):
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;
}
}
Ve aynı şeyi denetleyici olmayan bir yöntemde yaparsam (burada DI çalışmaz), şunu elde ederim 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;
}
}
Benim BootStrapper.cssınıf görünüyor gibi:
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)
{
}
}
Yukarıdaki satırda görüyorsanız container.RegisterType<IMyService , MyService>();, arayüz ve somut uygulaması ayrı bir modüldedir.
Ve benim Global.asax.cs:
protected void Application_Start()
{
Bootstrapper.Initialise();
AreaRegistration.RegisterAllAreas();
GlobalFilters.Filters.Add(new OfflineActionFilter());
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}
Nasıl enjekte IMyServiceiçinde MyLogicsınıfın?
Yanıtlar
Unity'ye sınıfın yapıcıya enjekte edilecek bir nesneye bağlı olduğunu söylemek için [InjectionConstructor] özelliğini kullanın MyLogic:
[InjectionConstructor]
public MyLogic(IMyService myService)
{
_myService = myService;
}
Aslında, [InjectionConstructor]enjekte edilen sınıf birden fazla kurucu içerdiğinde kullanılması önerilir. Bu nedenle, öznitelik belirsizliği gidermek için kullanılır. UnitySoru kodu kodun tüm parçalarını içermediğinden, neden gerekli türün çözülemeyeceği sadece benim hipotezimdi . Ancak aşağıdaki test kodunda [InjectionConstructor], yalnızca bir kurucu bildirildiği için özniteliğe gerek yoktur.
İşte test kodu.
IMyServiceArayüz tanımı:
public interface IMyService
{
string GetMyStringFromDLL();
}
ILogicArayüz tanımı:
public interface IMyLogic
{
string GetMyString();
}
MyLogicuygulama:
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;
}
}
MyServiceuygulama:
public class MyService : IMyService
{
public string GetMyStringFromDLL()
{
return "MyService.GetMyStringFromDLL() is called.";
}
}
Bootstrapperbaşlatma:
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;
}
}
HomeKontrolör uygulaması:
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} );
}
}
Ve son olarak, Homedenetleyicinin varsayılan eylem yöntemi yürütüldüğünde, aşağıdaki iki satır görüntülenir:
MyService.GetMyStringFromDLL() is called.
MyLogic.GetMyString() -> MyService.GetMyStringFromDLL() is called.
En son NopCommerce V1.90 üzerinde çalıştığımdan beri Unity ile çalışmadım, ancak IUnityResolver'ı uygulayan bir örnekte Resolve kullanırsanız, konteynerinize kaydettiğiniz her şeyin geri geleceğini hatırlıyorum.
Yani temel olarak, IMyService'i kaydettiniz, ancak aynı zamanda IMyLogic'i de kaydettirmelisiniz - o zaman "var logic = new MyLogic ();" yerine "var logic = resolver.Resolve (typeof (IMyLogic)); " ve sonra enjekte edilen parametreleriniz bağımlılık enjektörüne göre çözülecektir (veya eksiklerse uygun hataları alacaksınız).