.Net core的依賴注入


 

  vs新建的.net core項目內置了依賴注入功能,本文簡單地展示如何使用core的依賴注入,以及使用IOC容器(unity)來替換core自帶的依賴注入容器。

 

1.使用core項目的依賴注入

  新建.net core5 webapi 項目,創建MathBook.cs、EnglishBook.cs、Ibook.cs文件

using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace app
{
    public class MathBook: Ibook
    {
        public string read()
        {
            return "看數學書";
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace app
{
    public class EnglishBook: Ibook
    {
        public string read()
        {
            return "看英語書";
        }
    }
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace app
{
    public interface Ibook
    {
        string read();
    }
}

  在Startup.cs中嘗試注冊實例和調用實例。

namespace app
{
    public class Startup
    {
        public void ConfigureServices(IServiceCollection services)
        {
       //IserviceCollection提供注冊 services.AddSingleton
<Ibook, MathBook>(); } public void Configure(IApplicationBuilder app, IWebHostEnvironment env) {
       //IServiceProvider提供實例
app.ApplicationServices獲取
       var provider = app.ApplicationServices;

            //// 輸出
            var result = provider.GetService<Ibook>();
            Console.WriteLine(result.read());
        }
    }
}

運行程序,獲得結果。

  ServiceCollection注冊實例有三個方法,AddTransient、AddSingleton、AddScoped。對應提供的實例會有不同生命周期。

  Transient,每次調用GetServie方法都會創建一個新的實例。

  Singleton,整個程序運行期間只創建一個實例。

  Scoped,在同一個scope中,只創建一個實例。在一次http請求的整個過程中,默認共用一個scope。

 

  .net core項目已經作了依賴注入的實現,直接使用便可。

public void ConfigureServices(IServiceCollection services)
        {
            services.AddSingleton<Ibook, MathBook>();//注冊實例

            services.AddControllers();//使用api
        }
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

namespace app.Controllers
{
    [Route("api/[controller]")]
    [ApiController]
    public class BookController : ControllerBase
    {
        private Ibook _book;
        public BookController(Ibook book)
        {
            this._book = book;
        }

        [Route("toRead")]
        [HttpGet]
        public string toRead()
        {
            return _book.read();
        }
    }
}

  調用接口,可以獲得結果。

2.替換成其它ioc容器

  原有的依賴注入容器在面對大型項目會有些麻煩,原因是只能一個個進行注冊實例,有可能光是引用命名空間就占了幾百行。

  這里使用unity進行替換。

  安裝unity相關包

 

 

   在Program.cs中添加UseUnityServiceProvider()。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Unity;
using Unity.Microsoft.DependencyInjection;

namespace app
{
    public class Program
    {
        public static void Main(string[] args)
        {
            CreateHostBuilder(args).Build().Run();
        }

        public static IHostBuilder CreateHostBuilder(string[] args) =>
            Host.CreateDefaultBuilder(args)
                .UseUnityServiceProvider()
                .ConfigureWebHostDefaults(webBuilder =>
                {
                    webBuilder.UseStartup<Startup>();
                });
    }
}

  在Startup.cs中添加ConfigureContainer方法,用來處理untiy容器,往容器中注冊實例。

public void ConfigureContainer(IUnityContainer container)
        {
            ExeConfigurationFileMap fileMap = new ExeConfigurationFileMap();
            fileMap.ExeConfigFilename = Path.Combine(AppDomain.CurrentDomain.BaseDirectory + "unity.config");
            Configuration configuration = ConfigurationManager.OpenMappedExeConfiguration(fileMap, ConfigurationUserLevel.None);
            UnityConfigurationSection section = (UnityConfigurationSection)configuration.GetSection(UnityConfigurationSection.SectionName);

            section.Configure(container, "gContainer");//寫法一:給容器加載在配置文件中name為“gContainer”的<container>
        }

  上面是unity通過讀取配置文件去注冊,unity.config屬性需要設置為始終復制。

<configuration>
  <configSections>
    <section name="unity" type="Microsoft.Practices.Unity.Configuration.UnityConfigurationSection, Unity.Configuration"/>
  </configSections>
  <unity>
    <assembly name="app"/>
    <containers>
      <container name="gContainer">
        <register type="app.Ibook" mapTo="app.MathBook" />
      </container>
    </containers>
  </unity>
</configuration>

  Unity.Microsoft.DependencyInjection這個包的作用就是將unity的注冊實例行為轉化到.net core依賴容器,生成實例的生命周期是由.net core內置的容器進行管理。閱讀該包源代碼可以了解。

using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.DependencyInjection.Extensions;
using Microsoft.Extensions.Hosting;

namespace Unity.Microsoft.DependencyInjection
{
    public static class HostingExtension
    {
        private static ServiceProviderFactory _factory;


        public static IHostBuilder UseUnityServiceProvider(this IHostBuilder hostBuilder, IUnityContainer container = null)
        {
            _factory = new ServiceProviderFactory(container);

            return hostBuilder.UseServiceProviderFactory<IUnityContainer>(_factory)
                              .ConfigureServices((context, services) =>
                              {
                                  services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IUnityContainer>>(_factory));
                                  services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(_factory));
                              });
        }

        public static IWebHostBuilder UseUnityServiceProvider(this IWebHostBuilder hostBuilder, IUnityContainer container = null)
        {
            _factory = new ServiceProviderFactory(container);

#if NETCOREAPP1_1
            return hostBuilder.ConfigureServices((services) =>
            {
                services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IUnityContainer>>(_factory));
                services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(_factory));
            });
#else
            return hostBuilder.ConfigureServices((context, services) =>
            {
                services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IUnityContainer>>(_factory));
                services.Replace(ServiceDescriptor.Singleton<IServiceProviderFactory<IServiceCollection>>(_factory));
            });
#endif
        }
    }
}

  大致就是,使用了UseUnityServiceProvider的拓展方法后,unity的注冊實例,除了在unity自己的容器操作,同時還會對.net core的serviceCollection容器進行操作。

  運行程序,調用api/Book/toRead接口,成功得到結果。

  至此,成功使用unity去替換實現.net core中原有的依賴注入。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM