使用Unity.MVC让ASP.NET Framework4.8 MVC实现DI注入
在.Net(Core)的DI注入功能是内建的,我们在Program.cs里面就可以直接设定介面跟要对应的实作类别。但在.Net Framework4.8 MVC还没有内建DI容器这种东西,所以必须要另外安装DI套件,才能实现依赖注入(DI)
安装套件Unity & Unity.Mvc5
可以透过NuGet来安装
建立设定档UnityConfig.cs
在App_Start资料夹底下,新增UnityConfig.cs,预设内容如下。
using Unity;
using Unity.Mvc5;
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
建立对应
using Unity;
using Unity.Injection; //新增namespace
using Unity.Mvc5;
public static class UnityConfig
{
public static void RegisterComponents()
{
var container = new UnityContainer();
var rootPath = HttpRuntime.AppDomainAppPath;
string txtFilePath = System.IO.Path.Combine(rootPath, "Areas", "Viewer", "Content", "test_log.txt");
// register all your components with the container here
// it is NOT necessary to register your controllers
// e.g. container.RegisterType<ITestService, TestService>();
container.RegisterType<ILogService, TxtLogService>(new InjectionConstructor(txtFilePath)); //建立介面(ILogService)跟低阶类别(TxtLogService)的对应
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
public interface ILogService
{
void LogClear();
void Log(string content);
}
public class TxtLogService: ILogService
{
private readonly string _filePath;
public TxtLogService(string filePath)
{
_filePath = filePath;
}
public void LogClear()
{
// 使用StreamWriter清空文件内容
using (StreamWriter writer = new StreamWriter(_filePath, false))
{
writer.Write(string.Empty);
}
}
public void Log(string content)
{
using (StreamWriter writer = new StreamWriter(_filePath, true))
{
writer.WriteLine($"{content}\r\n");
}
}
}
建构子注入 & 应用
public class TestController : BaseController
{
private readonly ILogService _logService;
public TestController(
ILogService logService
)
{
_logService = logService
}
public async Task<ActionResult> Index()
{
_logService.LogClear();
_logService.Log($"point-start. => {DateTime.Now}");
}
}
底层类别替换
//UnityConfig.cs
container.RegisterType<ILogService, MailLogService>(); //低阶类别TxtLogService替换成MailLogService
public class MailLogService: ILogService
{
public void LogClear()
{
实作内容省略
...
}
public void Log(string content)
{
实作内容省略
...
}
}
生命週期设定
在.Net(Core)的DI里,注入的服务会有生命週期(请参考:.Net Core DI 服务生命週期)。
.Net(Core) | Unity.MVC | |
每次Post/Get Request在Application结束前, 都会使用相同的instance | builder.Services.AddScoped<ILogService, MailLogService>(); | container.RegisterType<ILogService, MailLogService>(new PerRequestLifetimeManager()); |
每次注入都会建立新的instance | builder.Services.AddTransient<ILogService, MailLogService>(); | container.RegisterType<ILogService, MailLogService>(new TransientLifetimeManager()); |
应用程式从开始到结束,使用的都是同一个instance | builder.Services.AddSingleton<ILogService, MailLogService>(); | container.RegisterType<ILogService, MailLogService>(new ContainerControlledLifetimeManager()); |