C# 如何在非控制器类中使用Unity MVC 4添加依赖项注入(DI)
因此,我使用Unity MVC-4实现依赖注入,它对我的C# 如何在非控制器类中使用Unity MVC 4添加依赖项注入(DI),c#,asp.net-mvc,dependency-injection,unity-container,C#,Asp.net Mvc,Dependency Injection,Unity Container,因此,我使用Unity MVC-4实现依赖注入,它对我的控制器类非常有效,但只要我尝试注入我的非控制器类,我就会得到NullReferenceException,我可以看到注入的对象没有被框架初始化。我将为您提供我正在使用的相应类: 控制器等级(DI工程): 如果我在非控制器方法中执行相同的操作(DI在这里不起作用),我会得到一个NullReferenceException: public inteface IMyLogic { string GetMyString(); } publ
控制器
类非常有效,但只要我尝试注入我的非控制器类,我就会得到NullReferenceException
,我可以看到注入的对象没有被框架初始化。我将为您提供我正在使用的相应类:
控制器
等级(DI工程):
如果我在非控制器方法中执行相同的操作(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)
{
}
}
如何在MyLogic
类中注入IMyService
?使用属性告诉UnityMyLogic
类依赖于要注入构造函数中的对象:
[InjectionConstructor]
public MyLogic(IMyService myService)
{
_myService = myService;
}
实际上,当注入的类包含多个构造函数时,建议使用[InjectionConstructor]
。因此,该属性用于解决歧义消除问题。这只是我的假设,Unity
无法解析所需类型,因为问题代码不包含代码的所有部分。但是在测试代码中,不需要[InjectionConstructor]
属性,因为只声明了一个构造函数
这里是测试代码
IMyService
接口定义:
public interface IMyService
{
string GetMyStringFromDLL();
}
public interface IMyLogic
{
string GetMyString();
}
ILogic
接口定义:
public interface IMyService
{
string GetMyStringFromDLL();
}
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;
}
}
public class MyService : IMyService
{
public string GetMyStringFromDLL()
{
return "MyService.GetMyStringFromDLL() is called.";
}
}
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} );
}
}
MyService
实现:
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;
}
}
public class MyService : IMyService
{
public string GetMyStringFromDLL()
{
return "MyService.GetMyStringFromDLL() is called.";
}
}
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} );
}
}
引导程序
初始化:
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
控制器的默认操作方法时,显示以下两行:
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));”,然后您的注入参数将根据依赖项注入器进行解析(或者,如果缺少这些参数,您将得到正确的错误).这是否回答了您的问题@拉胡尔·夏尔马:你的
Unity.Mvc4
运行时版本是什么?请公开您的IMyService
和MyService
定义。因为我将您的代码放在我的应用程序中(也使用Framework v4.5),并且它正在工作。@Rahul Sharma:根据您的问题描述,MyLogic
类中的\u myService
字段为null
(未初始化-将断点放在调试器中并检查)。这意味着在执行向容器注册类型MyLogic
映射之前,将调用MyLogic.GetMyString()
方法。所以,首先,有一些代码和这个问题相关,但在本文中并没有公开。第二,尝试移动两行container.RegisterType();容器。RegisterType@Jackdaw正如您在my Global.asax中看到的,Bootstrapper.Initialise()首先调用code>以确保容器与my service正确映射。我也尝试了你的其他建议,并将我的服务移动到Bootstrapper.BuildUnityContainer()
方法,但不幸的是结果是一样的。我也犯了同样的错误。如何检查Unity.Mvc4运行时版本?另外,公开我的IMyService
也不会有任何效果,因为生成错误的原因是\u myService
对象被接收为空。我仔细检查了MyService的逻辑,所有的东西都在那里。你是如何实例化MyLogic的?另外,除非您特别需要层次结构CallifeTimeManager,否则我建议使用TransientLifetimeManager、PerResolveLifetimeManager或PerThreadLifetimeManager。使用HierarchyAllifetimeManager,子容器并不总是与父容器相同。感谢您提供的详细答案,我非常感谢您的努力,但不幸的是,在我的情况下,它不起作用,这可能是因为我正在使用的统一版或其他一些我无法确定的东西。我尝试了你和其他人建议的所有组合,但根本不起作用。我通过在调用GetMyStringFromDLL
之前添加以下内容来解决此问题:var-sService=dependencysolver.Current.GetService()代码>。我甚至尝试了[InjectionConstructor]
属性,因为我的类有多个构造函数,但它仍然不起作用。你能在非控制器类中尝试上面的练习,看看它是否起作用吗?基本上,我的意思是尝试注入\u myService
,然后调用var-sService=\u myService.GetMyStringFromDLL()
在一个非控制器类中,它不是从控制器
类继承的。@Rahul Sharma:但这正是逻辑
类中的。逻辑
类不继承自控制器
,它具有var mystring=\u myService.GetMyStringFromDLL()代码>呼叫。我误解了什么吗?哦,是的,你是对的。我坚信你的解决方案足够了,但在我的情况下,它不起作用。我会把赏金给你的。再次感谢。如果您能告诉我您用于Unity
和MVC
的版本,那就太好了。@Rahul Sharma:我的测试环境是:目标版本.NET Framework 4.5,Unity 4.0.1
。如果你能修改你的例子来重现这个问题,我很乐意为你提供帮助。