如何在非控制器类中使用 Unity MVC 4 添加依赖注入 (DI)

Rah*_*rma 4 c# asp.net-mvc dependency-injection unity-container

因此,我使用 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

如果我在非控制器方法中做同样的事情(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;
    }
}
Run Code Online (Sandbox Code Playgroud)

我的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)
    {

    }

}
Run Code Online (Sandbox Code Playgroud)

如果您在上面的行中看到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);
}
Run Code Online (Sandbox Code Playgroud)

IMyService我怎样才能在课堂上注入MyLogic

Jac*_*daw 6

使用属性[InjectionConstructor]告诉 Unity 该类MyLogic依赖于要在构造函数中注入的对象:

[InjectionConstructor]
public MyLogic(IMyService myService)
{
   _myService = myService;
}
Run Code Online (Sandbox Code Playgroud)

实际上,[InjectionConstructor]当注入的类包含多个构造函数时,建议使用。因此,属性用于解决歧义。这只是我的假设,为什么Unity无法解析所需的类型,因为问题代码不包含代码的所有部分。但在下面的测试代码中[InjectionConstructor]不需要该属性,因为只声明了一个构造函数。

这是测试代码。

接口IMyService定义:

public interface IMyService
{
    string GetMyStringFromDLL();
}
Run Code Online (Sandbox Code Playgroud)

接口ILogic定义:

public interface IMyLogic
{
    string GetMyString();
}
Run Code Online (Sandbox Code Playgroud)

实施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;
    }
}
Run Code Online (Sandbox Code Playgroud)

实施MyService

public class MyService : IMyService
{
    public string GetMyStringFromDLL()
    {
        return "MyService.GetMyStringFromDLL() is called.";
    }
}
Run Code Online (Sandbox Code Playgroud)

初始化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;
    }
}
Run Code Online (Sandbox Code Playgroud)

控制器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} );
    }
}
Run Code Online (Sandbox Code Playgroud)

最后,当Home执行控制器的默认操作方法时,将显示以下两行:

MyService.GetMyStringFromDLL() is called.
MyLogic.GetMyString() -> MyService.GetMyStringFromDLL() is called.
Run Code Online (Sandbox Code Playgroud)