在 ASP.NET Core 3.0 上使用 Unity IoC / DI 容器 Container
為了要能夠在 ASP.NET Core 3.0 的專案內使用 Unity DI 容器功能,可以參考底下的步驟來實作出來
首先,請先建立一個空白的 ASP.NET Core 3.0 的專案
您需要安裝這個 Unity.Microsoft.DependencyInjection 套件 (在撰寫這篇文章的時候,最新的版本將是 5.10.2),其舊的 Github 專案位於 aspnet/DependencyInjection 現在已經轉移到了 aspnet/Extensions,其中關於相依性注入的原始碼位於 Extensions/src/DependencyInjection/
先打開 [Program.cs] 檔案,底下是建立專案的時候所產生的預設程式碼
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
為了要能夠在 ASP.NET Core 3.0 的專案內,使用 Unity IoC 容器作為相依性注入管理之用,請將 [Program.cs] 檔案的內容,修改成為底下程式碼
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.UseServiceProviderFactory<IUnityContainer>(new UnityContainerFactory())
.ConfigureWebHostDefaults(webBuilder =>
{
webBuilder.UseStartup<Startup>();
});
}
partial class UnityContainerFactory : IServiceProviderFactory<IUnityContainer>
{
private IServiceCollection Services { get; set; }
public IUnityContainer CreateBuilder(IServiceCollection services)
{
Services = services;
return new UnityContainer();
}
public IServiceProvider CreateServiceProvider(IUnityContainer containerBuilder)
=> containerBuilder.BuildServiceProvider(Services);
}
在上面的程式碼中,會先要建立一個新的類別 [UnityContainerFactory] 該類別需要實作 [IServiceProviderFactory] 介面,由於在這裡將會要導入 Unity 容器,因此,將會實作 [IServiceProviderFactory] 這個泛型介面。
另外,在原先的 CreateHostBuilder 方法內,請加入
.UseServiceProviderFactory<IUnityContainer>(new UnityContainerFactory()
方法呼叫,以啟用 Unity 容器功能。
現在要轉移到 [Startup.cs] 這個檔案內,底下為建立專案後所產生的原始碼。
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync("Hello World!");
});
});
}
}
接下來要修改 [Startup.cs] 檔案,使用 Unity 相依性注入容器的註冊與解析工作,請將 [Startup.cs] 檔案內容,修改成為底下的程式碼。
public interface IMessage
{
string Send(string message);
}
public class ConsoleMessage : IMessage
{
public string Send(string message)
{
string result = $"ConsoleMessage :{message}";
Console.WriteLine(result);
return result;
}
}
public class Startup
{
// This method gets called by the runtime. Use this method to add services to the container.
// For more information on how to configure your application, visit https://go.microsoft.com/fwlink/?LinkID=398940
public void ConfigureServices(IServiceCollection services)
{
}
public void ConfigureContainer(IUnityContainer container)
{
container.RegisterType<IMessage, ConsoleMessage>();
}
// This method gets called by the runtime. Use this method to configure the HTTP request pipeline.
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IMessage message)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseRouting();
app.UseEndpoints(endpoints =>
{
endpoints.MapGet("/", async context =>
{
await context.Response.WriteAsync(message.Send("Hello World!"));
});
});
}
}
在這個檔案內的最上方,會先建立一個介面 IMessage,與實作該介面的具體實作類別 ConsoleMessage
接著,請在 Startup 類別內,建立一個
public void ConfigureContainer(IUnityContainer container)
方法,由於該方法會傳入一個 IUnityContainer,所以,便可以在這裡進行所需要注入對應型別的註冊宣告,這裡將會使用 container.RegisterType<IMessage, ConsoleMessage>();
這個敘述,建立起 IMessage 介面與 ConsoleMessage 類別的對應關係。
現在要來測試,是否可以在 ASP.NET Core 3.0 專案內來使用 Unity 容器註冊的型別,直接注入實作執行個體來直接使用,在這裡將會修改 Configure 方法,修改成為
public void Configure(IApplicationBuilder app, IWebHostEnvironment env, IMessage message)
其中,在該方法參數的最後面,加入 IMessage message
參數,期望相依性管理容器能夠注入執行個體到這個方法內,如此,便可以在 await context.Response.WriteAsync(message.Send("Hello World!"));
敘述內呼叫 IMessage 具體實作的執行個體方法了。