2019年11月27日 星期三

在 ASP.NET Core 3.0 上使用 Unity IoC / DI 容器 Container

在 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] 檔案,底下是建立專案的時候所產生的預設程式碼
C Sharp / C#
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] 檔案的內容,修改成為底下程式碼
C Sharp / C#
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] 這個檔案內,底下為建立專案後所產生的原始碼。
C Sharp / C#
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] 檔案內容,修改成為底下的程式碼。
C Sharp / C#
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 具體實作的執行個體方法了。



沒有留言:

張貼留言