1. 程式人生 > >.net core2.1 三層中使用Autofac代替原來Ioc

.net core2.1 三層中使用Autofac代替原來Ioc

mpat quest cookie sse asi viewdata inter .net core control

首先,現有的三層項目的結構

技術分享圖片

其中 Repository

 public interface IPersonRepository
    {
         string Eat();
    }
public class PersonRepository : IPersonRepository
    {
        public string Eat()
        {
            return "吃飯";
        }
    }

Service

public interface IPersonService
    {
        
string Eat(); }
 public class PersonService : IPersonService
    {
       private  IPersonRepository _personRespository;
        //通過構造函數註入 repository
        public  PersonService(IPersonRepository personRespository)
        {
          _personRespository = personRespository;
        }
        
public string Eat() { return _personRespository.Eat(); } }

一、安裝Autofac

nuget上安裝Autofac

技術分享圖片

二、替換內置的DI框架

    將Startup.cs中的ConfigureServices返回類型改為IServiceProvider,然後新起一個方法RegisterAutofac把創建容器的代碼放到其中,然後建一個AutofacConfig 類來存放具體的註入代碼,避免

  Startup.cs文件代碼過多混亂。

 public IServiceProvider ConfigureServices(IServiceCollection services)
        {
            services.Configure<CookiePolicyOptions>(options =>
            {
                // This lambda determines whether user consent for non-essential cookies is needed for a given request.
                options.CheckConsentNeeded = context => true;
                options.MinimumSameSitePolicy = SameSiteMode.None;
            });
            services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);
            return RegisterAutofac(services);//註冊Autofac
        }
        private IServiceProvider RegisterAutofac(IServiceCollection services)
        {
            //實例化Autofac容器
            var builder = new ContainerBuilder();
            builder.Populate(services);
            //Autofac註冊對象        
             AutofacConfig.RegisterObj(builder);
            var Container = builder.Build();
            //第三方IOC接管 core內置DI容器 
            return new AutofacServiceProvider(Container);
        }
 public class AutofacConfig
    {
        public static void RegisterObj(ContainerBuilder builder)
        {
            //註冊Service中的組件,Service中的類要以Service結尾,否則註冊失敗
            builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();
            //註冊Repository中的組件,Repository中的類要以Repository結尾,否則註冊失敗
            builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();
        }
        /// <summary>
        /// 根據程序集名稱獲取程序集
        /// </summary>
        /// <param name="AssemblyName">程序集名稱</param>
        /// <returns></returns>
        public static Assembly GetAssemblyByName(String AssemblyName)
        {
            return Assembly.Load(AssemblyName);
        }
    }

此時Autofac基本使用已經配好了。

三、測試效果

修改HomeController 實現註入Service

 public class HomeController : Controller
    {
        private IPersonService _personService;
      
        //通過構造函數註入Service
        public HomeController(IPersonService personService)
        {
            _personService = personService;
        }
        public IActionResult Index()
        {
            ViewBag.eat = _personService.Eat();
            return View();
        }
}

頁面結果:

技術分享圖片

四、一個接口多個實現的情況

   比喻我現在在Service 中建三個類,IPayService, WxPayService,AliPayService,其中WxPayService,AliPayService都實現接口IPayService。

 public interface IPayService
    {
        string Pay();
    }
public class AliPayService : IPayService
    {
        public string Pay()
        {
            return "支付寶支付";
        }
    }
 public class WxPayService : IPayService
    {
        public string Pay()
        {
            return "微信支付";
        }
    }

先試一下結果,修改HomeController

 public class HomeController : Controller
    {
        private IPersonService _personService;
        private IPayService _payService;
      
        //通過構造函數註入Service
        public HomeController(IPersonService personService,IPayService payService)
        {
            _personService = personService;
            _payService = payService;
        }
        public IActionResult Index()
        {
            ViewBag.eat = _personService.Eat();
            ViewBag.pay = _payService.Pay();
            return View();
        }
    }

View

@{
    ViewData["Title"] = "Home Page";
}
@ViewBag.eat <br />
@ViewBag.pay

輸出頁面:

技術分享圖片

最後得到的是微信支付,因為兩個對象實現一個接口的時候,註冊時後面註冊的會覆蓋前面註冊的。如果我想得到支付寶支付要怎麽做呢?

 我們可以用另外一種註冊方式RegisterType,修改註冊方式AutofacConfig.cs。

public static void RegisterObj(ContainerBuilder builder)
        {
            //註冊Service中的組件,Service中的類要以Service結尾,否則註冊失敗
            builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Service")).Where(a => a.Name.EndsWith("Service")).AsImplementedInterfaces();
            //註冊Repository中的組件,Repository中的類要以Repository結尾,否則註冊失敗
            builder.RegisterAssemblyTypes(GetAssemblyByName("WXL.Repository")).Where(a => a.Name.EndsWith("Repository")).AsImplementedInterfaces();
            //單獨註冊
            builder.RegisterType<WxPayService>().Named<IPayService>(typeof(WxPayService).Name);
            builder.RegisterType<AliPayService>().Named<IPayService>(typeof(AliPayService).Name);
        }
        /// <summary>
        /// 根據程序集名稱獲取程序集
        /// </summary>
        /// <param name="AssemblyName">程序集名稱</param>
        /// <returns></returns>
        public static Assembly GetAssemblyByName(String AssemblyName)
        {
            return Assembly.Load(AssemblyName);
        }

用Named區分兩個組件的不同,後面的typeof(WxPayService).Name 是任意字符串,這裏直接用這個類名作標識,方便取出來時也是用這個名字,不易忘記。

然後就是取出對應的組件了,取的時候用Autofac的 上下文(IComponentContext) ,修改HomeController

 public class HomeController : Controller
    {
        private IPersonService _personService;
        private IPayService _wxPayService;
        private IPayService _aliPayService;
        private IComponentContext _componentContext;//Autofac上下文
        //通過構造函數註入Service
        public HomeController(IPersonService personService, IComponentContext componentContext)
        {
            _personService = personService;
            _componentContext = componentContext;
            //解釋組件
            _wxPayService = componentContext.ResolveNamed<IPayService>(typeof(WxPayService).Name);
            _aliPayService =componentContext.ResolveNamed<IPayService>(typeof(AliPayService).Name);
        }
        public IActionResult Index()
        {
            ViewBag.eat = _personService.Eat();
            ViewBag.wxPay = _wxPayService.Pay();
            ViewBag.aliPay = _aliPayService.Pay();
            return View();
        }
    }

Index View:

@{
    ViewData["Title"] = "Home Page";
}
@ViewBag.eat <br />
@ViewBag.wxPay <br />
@ViewBag.aliPay

結果:

技術分享圖片

完成。

    

.net core2.1 三層中使用Autofac代替原來Ioc