使用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()); |